• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef NAPI_EXPERIMENTAL
16 #define NAPI_EXPERIMENTAL
17 #endif
18 
19 #ifdef ENABLE_HITRACE
20 #include <sys/prctl.h>
21 #endif
22 
23 #ifdef ENABLE_CONTAINER_SCOPE
24 #include "core/common/container_scope.h"
25 #endif
26 #include "ecmascript/napi/include/jsnapi.h"
27 #include "native_api_internal.h"
28 #include "native_engine/impl/ark/ark_native_engine.h"
29 #include "native_engine/impl/ark/ark_native_reference.h"
30 #include "native_engine/native_create_env.h"
31 #include "native_engine/native_property.h"
32 #include "native_engine/native_sendable.h"
33 #include "native_engine/native_utils.h"
34 #include "native_engine/native_value.h"
35 #include "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     auto funcInfo = reinterpret_cast<NapiFunctionInfo *>(function->GetData(vm));
1222     if (funcInfo != nullptr) {
1223         scopeId = funcInfo->scopeId;
1224     }
1225     OHOS::Ace::ContainerScope containerScope(scopeId);
1226 #endif
1227     panda::JSValueRef* value =
1228         function->CallForNapi(vm, thisObj, reinterpret_cast<panda::JSValueRef *const*>(argv), argc);
1229     // if pending exception, value will be a pointer to JSTaggedValue::Hole.
1230     if (UNLIKELY(!NapiStatusValidationCheck(value))) {
1231         HILOG_ERROR("pending exception when js function called, print exception info: ");
1232         panda::JSNApi::PrintExceptionInfo(vm);
1233         result = nullptr;
1234         reinterpret_cast<NativeEngine *>(env)->lastException_ = panda::JSNApi::GetUncaughtException(vm);
1235         return napi_set_last_error(env, napi_pending_exception);
1236     }
1237     if (result) {
1238         *result = reinterpret_cast<napi_value>(value);
1239     }
1240     return napi_clear_last_error(env);
1241 }
1242 
napi_new_instance(napi_env env,napi_value constructor,size_t argc,const napi_value * argv,napi_value * result)1243 NAPI_EXTERN napi_status napi_new_instance(napi_env env,
1244                                           napi_value constructor,
1245                                           size_t argc,
1246                                           const napi_value* argv,
1247                                           napi_value* result)
1248 {
1249     NAPI_PREAMBLE(env);
1250     CHECK_ARG(env, constructor);
1251     if (argc > 0) {
1252         CHECK_ARG(env, argv);
1253     }
1254     CHECK_ARG(env, result);
1255 
1256     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1257     panda::JsiFastNativeScope fastNativeScope(vm);
1258 
1259     RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef*>(constructor)->IsFunction(vm),
1260         napi_function_expected);
1261     panda::FunctionRef* constructorVal = reinterpret_cast<panda::FunctionRef*>(constructor);
1262     panda::JSValueRef* instance = constructorVal->ConstructorOptimize(vm,
1263         reinterpret_cast<panda::JSValueRef**>(const_cast<napi_value*>(argv)), argc);
1264     if (tryCatch.HasCaught()) {
1265         HILOG_ERROR("CreateInstance occur Exception");
1266         *result = nullptr;
1267     } else {
1268         *result = reinterpret_cast<napi_value>(instance);
1269     }
1270     return GET_RETURN_STATUS(env);
1271 }
1272 
napi_instanceof(napi_env env,napi_value object,napi_value constructor,bool * result)1273 NAPI_EXTERN napi_status napi_instanceof(napi_env env, napi_value object, napi_value constructor, bool* result)
1274 {
1275     NAPI_PREAMBLE(env);
1276     CHECK_ARG(env, object);
1277     CHECK_ARG(env, constructor);
1278     CHECK_ARG(env, result);
1279 
1280     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1281     panda::JsiFastNativeScope fastNativeScope(vm);
1282 
1283     auto nativeValue = LocalValueFromJsValue(object);
1284     auto nativeConstructor = LocalValueFromJsValue(constructor);
1285     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
1286     RETURN_STATUS_IF_FALSE(env, nativeConstructor->IsFunction(vm), napi_function_expected);
1287     *result = nativeValue->InstanceOf(vm, nativeConstructor);
1288 
1289     return GET_RETURN_STATUS(env);
1290 }
1291 
1292 // Methods to work with napi_callbacks
1293 // 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)1294 NAPI_EXTERN napi_status napi_get_cb_info(napi_env env,              // [in] NAPI environment handle
1295                                          napi_callback_info cbinfo, // [in] Opaque callback-info handle
1296                                          size_t* argc,         // [in-out] Specifies the size of the provided argv array
1297                                                                // and receives the actual count of args.
1298                                          napi_value* argv,     // [out] Array of values
1299                                          napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
1300                                          void** data)          // [out] Receives the data pointer for the callback.
1301 {
1302     CHECK_ENV(env);
1303     CHECK_ARG(env, cbinfo);
1304 
1305     auto info = reinterpret_cast<panda::JsiRuntimeCallInfo*>(cbinfo);
1306     if ((argc != nullptr) && (argv != nullptr)) {
1307 #ifdef ENABLE_CONTAINER_SCOPE
1308         auto *vm = info->GetVM();
1309 #endif
1310         size_t i = 0;
1311         if (*argc > 0) {
1312             size_t j = static_cast<size_t>(info->GetArgsNumber());
1313             for (; i < j && i < *argc; i++) {
1314                 panda::Local<panda::JSValueRef> value = info->GetCallArgRef(i);
1315 #ifdef ENABLE_CONTAINER_SCOPE
1316                 FunctionSetContainerId(vm, value);
1317 #endif
1318                 argv[i] = JsValueFromLocalValue(value);
1319             }
1320         } else {
1321             i = static_cast<size_t>(info->GetArgsNumber());
1322         }
1323         if (i < *argc) {
1324             napi_value undefined = JsValueFromLocalValue(
1325                 panda::JSValueRef::Undefined(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm()));
1326             for (; i < *argc; i++) {
1327                 argv[i] = undefined;
1328             }
1329         }
1330     }
1331     if (argc != nullptr) {
1332         *argc = static_cast<size_t>(info->GetArgsNumber());
1333     }
1334     if (this_arg != nullptr) {
1335         *this_arg = JsValueFromLocalValue(info->GetThisRef());
1336     }
1337     if (data != nullptr) {
1338         auto funcInfo = static_cast<NapiFunctionInfo*>(info->GetData());
1339         if (funcInfo != nullptr) {
1340             *data = funcInfo->data;
1341         }
1342     }
1343 
1344     return napi_clear_last_error(env);
1345 }
1346 
napi_get_new_target(napi_env env,napi_callback_info cbinfo,napi_value * result)1347 NAPI_EXTERN napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, napi_value* result)
1348 {
1349     NAPI_PREAMBLE(env);
1350     CHECK_ARG(env, cbinfo);
1351     CHECK_ARG(env, result);
1352 
1353     auto info = reinterpret_cast<panda::JsiRuntimeCallInfo*>(cbinfo);
1354     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1355     auto thisVarObj = info->GetThisRef();
1356 #ifdef ENABLE_CONTAINER_SCOPE
1357     panda::Local<panda::JSValueRef> newValue = info->GetNewTargetRef();
1358     FunctionSetContainerId(vm, newValue);
1359     auto functionVal = newValue;
1360 #else
1361     auto functionVal = info->GetNewTargetRef();
1362 #endif
1363     if (thisVarObj->InstanceOf(vm, functionVal)) {
1364         *result = JsValueFromLocalValue(functionVal);
1365     } else {
1366         *result = nullptr;
1367     }
1368 
1369     return GET_RETURN_STATUS(env);
1370 }
1371 
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)1372 NAPI_EXTERN napi_status napi_define_class(napi_env env,
1373                                           const char* utf8name,
1374                                           size_t length,
1375                                           napi_callback constructor,
1376                                           void* data,
1377                                           size_t property_count,
1378                                           const napi_property_descriptor* properties,
1379                                           napi_value* result)
1380 {
1381     NAPI_PREAMBLE(env);
1382     CHECK_ARG(env, utf8name);
1383     RETURN_STATUS_IF_FALSE(env, length == NAPI_AUTO_LENGTH || length <= INT_MAX, napi_object_expected);
1384     CHECK_ARG(env, constructor);
1385     if (property_count > 0) {
1386         CHECK_ARG(env, properties);
1387     }
1388     CHECK_ARG(env, result);
1389 
1390     auto callback = reinterpret_cast<NapiNativeCallback>(constructor);
1391     auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1392 
1393     size_t nameLength = std::min(length, strlen(utf8name));
1394     char newName[nameLength + 1];
1395     if (strncpy_s(newName, nameLength + 1, utf8name, nameLength) != EOK) {
1396         HILOG_ERROR("napi_define_class strncpy_s failed");
1397         *result = nullptr;
1398     } else {
1399         auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1400         panda::JsiFastNativeScope fastNativeScope(vm);
1401         EscapeLocalScope scope(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
1402         auto resultValue = NapiDefineClass(env, newName, callback, data, nativeProperties, property_count);
1403         *result = JsValueFromLocalValue(scope.Escape(resultValue));
1404     }
1405 
1406     return GET_RETURN_STATUS(env);
1407 }
1408 
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)1409 NAPI_EXTERN napi_status napi_define_sendable_class(napi_env env,
1410                                                    const char* utf8name,
1411                                                    size_t length,
1412                                                    napi_callback constructor,
1413                                                    void* data,
1414                                                    size_t property_count,
1415                                                    const napi_property_descriptor* properties,
1416                                                    napi_value parent,
1417                                                    napi_value* result)
1418 {
1419     NAPI_PREAMBLE(env);
1420     CHECK_ARG(env, utf8name);
1421     RETURN_STATUS_IF_FALSE(env, length == NAPI_AUTO_LENGTH || length <= INT_MAX,
1422                            napi_object_expected);
1423     CHECK_ARG(env, constructor);
1424     if (property_count > 0) {
1425         CHECK_ARG(env, properties);
1426     }
1427     CHECK_ARG(env, result);
1428 
1429     auto callback = reinterpret_cast<NapiNativeCallback>(constructor);
1430     auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1431 
1432     size_t nameLength = std::min(length, strlen(utf8name));
1433     char newName[nameLength + 1];
1434     if (strncpy_s(newName, nameLength + 1, utf8name, nameLength) != EOK) {
1435         HILOG_ERROR("napi_define_sendable_class strncpy_s failed");
1436         *result = nullptr;
1437     } else {
1438         EscapeLocalScope scope(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
1439         auto resultValue =
1440             NapiDefineSendableClass(env, newName, callback, data, nativeProperties, property_count, parent);
1441         *result = JsValueFromLocalValue(scope.Escape(resultValue));
1442     }
1443 
1444     return GET_RETURN_STATUS(env);
1445 }
1446 
napi_create_sendable_object_with_properties(napi_env env,size_t property_count,const napi_property_descriptor * properties,napi_value * result)1447 NAPI_EXTERN napi_status napi_create_sendable_object_with_properties(napi_env env,
1448                                                                     size_t property_count,
1449                                                                     const napi_property_descriptor* properties,
1450                                                                     napi_value* result)
1451 {
1452     CHECK_ENV(env);
1453     CHECK_ARG(env, result);
1454 
1455     auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1456     auto object = NapiCreateSObjectWithProperties(env, property_count, nativeProperties);
1457     *result = JsValueFromLocalValue(object);
1458 
1459     return napi_clear_last_error(env);
1460 }
1461 
napi_create_map(napi_env env,napi_value * result)1462 NAPI_EXTERN napi_status napi_create_map(napi_env env, napi_value* result)
1463 {
1464     CHECK_ENV(env);
1465     CHECK_ARG(env, result);
1466 
1467     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1468     Local<panda::ArrayRef> object = panda::MapRef::New(vm);
1469     *result = JsValueFromLocalValue(object);
1470 
1471     return napi_clear_last_error(env);
1472 }
1473 
napi_create_sendable_map(napi_env env,napi_value * result)1474 NAPI_EXTERN napi_status napi_create_sendable_map(napi_env env, napi_value* result)
1475 {
1476     CHECK_ENV(env);
1477     CHECK_ARG(env, result);
1478 
1479     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1480     Local<panda::ArrayRef> object = panda::SendableMapRef::New(vm);
1481     *result = JsValueFromLocalValue(object);
1482 
1483     return napi_clear_last_error(env);
1484 }
1485 
napi_map_set_property(napi_env env,napi_value map,napi_value key,napi_value value)1486 NAPI_EXTERN napi_status napi_map_set_property(napi_env env, napi_value map, napi_value key, napi_value value)
1487 {
1488     NAPI_PREAMBLE(env);
1489     CHECK_ARG(env, map);
1490     CHECK_ARG(env, key);
1491     CHECK_ARG(env, value);
1492 
1493     auto nativeValue = LocalValueFromJsValue(map);
1494     auto propKey = LocalValueFromJsValue(key);
1495     auto propValue = LocalValueFromJsValue(value);
1496     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1497     panda::JsiFastNativeScope fastNativeScope(vm);
1498     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1499     if (LIKELY(nativeValue->IsMap(vm))) {
1500         Local<panda::MapRef> mapRef(nativeValue);
1501         mapRef->Set(vm, propKey, propValue);
1502     } else {
1503         Local<panda::SendableMapRef> mapRef(nativeValue);
1504         mapRef->Set(vm, propKey, propValue);
1505     }
1506 
1507     return GET_RETURN_STATUS(env);
1508 }
1509 
napi_map_set_named_property(napi_env env,napi_value map,const char * utf8name,napi_value value)1510 NAPI_EXTERN napi_status napi_map_set_named_property(napi_env env,
1511                                                     napi_value map,
1512                                                     const char* utf8name,
1513                                                     napi_value value)
1514 {
1515     NAPI_PREAMBLE(env);
1516     CHECK_ARG(env, map);
1517     CHECK_ARG(env, utf8name);
1518     CHECK_ARG(env, value);
1519 
1520     auto nativeValue = LocalValueFromJsValue(map);
1521     auto propVal = LocalValueFromJsValue(value);
1522     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1523     panda::JsiFastNativeScope fastNativeScope(vm);
1524     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1525     Local<panda::MapRef> mapRef(nativeValue);
1526     if (LIKELY(nativeValue->IsMap(vm))) {
1527         Local<panda::MapRef> mapRef(nativeValue);
1528         mapRef->Set(vm, utf8name, propVal);
1529     } else {
1530         Local<panda::SendableMapRef> mapRef(nativeValue);
1531         mapRef->Set(vm, utf8name, propVal);
1532     }
1533 
1534     return GET_RETURN_STATUS(env);
1535 }
1536 
napi_map_get_property(napi_env env,napi_value map,napi_value key,napi_value * result)1537 NAPI_EXTERN napi_status napi_map_get_property(napi_env env, napi_value map, napi_value key, napi_value* result)
1538 {
1539     NAPI_PREAMBLE(env);
1540     CHECK_ARG(env, map);
1541     CHECK_ARG(env, key);
1542     CHECK_ARG(env, result);
1543 
1544     auto nativeValue = LocalValueFromJsValue(map);
1545     auto propKey = LocalValueFromJsValue(key);
1546     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1547     panda::JsiFastNativeScope fastNativeScope(vm);
1548     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1549     Local<JSValueRef> value;
1550     if (LIKELY(nativeValue->IsMap(vm))) {
1551         Local<panda::MapRef> mapRef(nativeValue);
1552         value = mapRef->Get(vm, propKey);
1553     } else {
1554         Local<panda::SendableMapRef> mapRef(nativeValue);
1555         value = mapRef->Get(vm, propKey);
1556     }
1557     RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(value), napi_object_expected);
1558     *result = JsValueFromLocalValue(value);
1559 
1560     return GET_RETURN_STATUS(env);
1561 }
1562 
napi_map_get_named_property(napi_env env,napi_value map,const char * utf8name,napi_value * result)1563 NAPI_EXTERN napi_status napi_map_get_named_property(napi_env env,
1564                                                     napi_value map,
1565                                                     const char* utf8name,
1566                                                     napi_value* result)
1567 {
1568     NAPI_PREAMBLE(env);
1569     CHECK_ARG(env, map);
1570     CHECK_ARG(env, utf8name);
1571     CHECK_ARG(env, result);
1572 
1573     auto nativeValue = LocalValueFromJsValue(map);
1574     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1575     panda::JsiFastNativeScope fastNativeScope(vm);
1576     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1577     Local<JSValueRef> value;
1578     if (LIKELY(nativeValue->IsMap(vm))) {
1579         Local<panda::MapRef> mapRef(nativeValue);
1580         value = mapRef->Get(vm, utf8name);
1581     } else {
1582         Local<panda::SendableMapRef> mapRef(nativeValue);
1583         value = mapRef->Get(vm, utf8name);
1584     }
1585     RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(value), napi_object_expected);
1586     *result = JsValueFromLocalValue(value);
1587 
1588     return GET_RETURN_STATUS(env);
1589 }
1590 
napi_map_has_property(napi_env env,napi_value map,napi_value key,bool * result)1591 NAPI_EXTERN napi_status napi_map_has_property(napi_env env, napi_value map, napi_value key, bool* result)
1592 {
1593     NAPI_PREAMBLE(env);
1594     CHECK_ARG(env, map);
1595     CHECK_ARG(env, key);
1596     CHECK_ARG(env, result);
1597 
1598     auto nativeValue = LocalValueFromJsValue(map);
1599     auto propKey = LocalValueFromJsValue(key);
1600     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1601     panda::JsiFastNativeScope fastNativeScope(vm);
1602     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1603     bool value;
1604     if (LIKELY(nativeValue->IsMap(vm))) {
1605         Local<panda::MapRef> mapRef(nativeValue);
1606         value = mapRef->Has(vm, propKey);
1607     } else {
1608         Local<panda::SendableMapRef> mapRef(nativeValue);
1609         value = mapRef->Has(vm, propKey);
1610     }
1611     *result = value;
1612 
1613     return GET_RETURN_STATUS(env);
1614 }
1615 
napi_map_has_named_property(napi_env env,napi_value map,const char * utf8name,bool * result)1616 NAPI_EXTERN napi_status napi_map_has_named_property(napi_env env, napi_value map, const char* utf8name, bool* result)
1617 {
1618     NAPI_PREAMBLE(env);
1619     CHECK_ARG(env, map);
1620     CHECK_ARG(env, utf8name);
1621     CHECK_ARG(env, result);
1622 
1623     auto nativeValue = LocalValueFromJsValue(map);
1624     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1625     panda::JsiFastNativeScope fastNativeScope(vm);
1626     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1627     bool value;
1628     if (LIKELY(nativeValue->IsMap(vm))) {
1629         Local<panda::MapRef> mapRef(nativeValue);
1630         value = mapRef->Has(vm, utf8name);
1631     } else {
1632         Local<panda::SendableMapRef> mapRef(nativeValue);
1633         value = mapRef->Has(vm, utf8name);
1634     }
1635     *result = value;
1636 
1637     return GET_RETURN_STATUS(env);
1638 }
1639 
napi_map_delete_property(napi_env env,napi_value map,napi_value key)1640 NAPI_EXTERN napi_status napi_map_delete_property(napi_env env, napi_value map, napi_value key)
1641 {
1642     NAPI_PREAMBLE(env);
1643     CHECK_ARG(env, map);
1644     CHECK_ARG(env, key);
1645 
1646     auto nativeValue = LocalValueFromJsValue(map);
1647     auto propKey = LocalValueFromJsValue(key);
1648     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1649     panda::JsiFastNativeScope fastNativeScope(vm);
1650     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1651     if (LIKELY(nativeValue->IsMap(vm))) {
1652         Local<panda::MapRef> mapRef(nativeValue);
1653         mapRef->Delete(vm, propKey);
1654     } else {
1655         Local<panda::SendableMapRef> mapRef(nativeValue);
1656         mapRef->Delete(vm, propKey);
1657     }
1658 
1659     return GET_RETURN_STATUS(env);
1660 }
1661 
napi_map_clear(napi_env env,napi_value map)1662 NAPI_EXTERN napi_status napi_map_clear(napi_env env, napi_value map)
1663 {
1664     NAPI_PREAMBLE(env);
1665     CHECK_ARG(env, map);
1666 
1667     auto nativeValue = LocalValueFromJsValue(map);
1668     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1669     panda::JsiFastNativeScope fastNativeScope(vm);
1670     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1671     if (LIKELY(nativeValue->IsMap(vm))) {
1672         Local<panda::MapRef> mapRef(nativeValue);
1673         mapRef->Clear(vm);
1674     } else {
1675         Local<panda::SendableMapRef> mapRef(nativeValue);
1676         mapRef->Clear(vm);
1677     }
1678 
1679     return GET_RETURN_STATUS(env);
1680 }
1681 
napi_map_get_size(napi_env env,napi_value map,uint32_t * result)1682 NAPI_EXTERN napi_status napi_map_get_size(napi_env env, napi_value map, uint32_t* result)
1683 {
1684     NAPI_PREAMBLE(env);
1685     CHECK_ARG(env, map);
1686     CHECK_ARG(env, result);
1687 
1688     auto nativeValue = LocalValueFromJsValue(map);
1689     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1690     panda::JsiFastNativeScope fastNativeScope(vm);
1691     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1692     uint32_t value;
1693     if (LIKELY(nativeValue->IsMap(vm))) {
1694         Local<panda::MapRef> mapRef(nativeValue);
1695         value = static_cast<uint32_t>(mapRef->GetSize(vm));
1696     } else {
1697         Local<panda::SendableMapRef> mapRef(nativeValue);
1698         value = static_cast<uint32_t>(mapRef->GetSize(vm));
1699     }
1700     *result = value;
1701 
1702     return GET_RETURN_STATUS(env);
1703 }
1704 
napi_map_get_entries(napi_env env,napi_value map,napi_value * result)1705 NAPI_EXTERN napi_status napi_map_get_entries(napi_env env, napi_value map, napi_value* result)
1706 {
1707     NAPI_PREAMBLE(env);
1708     CHECK_ARG(env, map);
1709     CHECK_ARG(env, result);
1710 
1711     auto nativeValue = LocalValueFromJsValue(map);
1712     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1713     panda::JsiFastNativeScope fastNativeScope(vm);
1714     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1715     if (LIKELY(nativeValue->IsMap(vm))) {
1716         Local<panda::MapRef> mapRef(nativeValue);
1717         Local<panda::ArrayRef> arrayVal = mapRef->GetEntries(vm);
1718         *result = JsValueFromLocalValue(arrayVal);
1719     } else {
1720         Local<panda::SendableMapRef> mapRef(nativeValue);
1721         Local<panda::SendableArrayRef> arrayVal = mapRef->GetEntries(vm);
1722         *result = JsValueFromLocalValue(arrayVal);
1723     }
1724     return GET_RETURN_STATUS(env);
1725 }
1726 
napi_map_get_keys(napi_env env,napi_value map,napi_value * result)1727 NAPI_EXTERN napi_status napi_map_get_keys(napi_env env, napi_value map, napi_value* result)
1728 {
1729     NAPI_PREAMBLE(env);
1730     CHECK_ARG(env, map);
1731     CHECK_ARG(env, result);
1732 
1733     auto nativeValue = LocalValueFromJsValue(map);
1734     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1735     panda::JsiFastNativeScope fastNativeScope(vm);
1736     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1737     if (LIKELY(nativeValue->IsMap(vm))) {
1738         Local<panda::MapRef> mapRef(nativeValue);
1739         Local<panda::ArrayRef> arrayVal = mapRef->GetKeys(vm);
1740         *result = JsValueFromLocalValue(arrayVal);
1741     } else {
1742         Local<panda::SendableMapRef> mapRef(nativeValue);
1743         Local<panda::SendableArrayRef> arrayVal = mapRef->GetKeys(vm);
1744         *result = JsValueFromLocalValue(arrayVal);
1745     }
1746     return GET_RETURN_STATUS(env);
1747 }
1748 
napi_map_get_values(napi_env env,napi_value map,napi_value * result)1749 NAPI_EXTERN napi_status napi_map_get_values(napi_env env, napi_value map, napi_value* result)
1750 {
1751     NAPI_PREAMBLE(env);
1752     CHECK_ARG(env, map);
1753     CHECK_ARG(env, result);
1754 
1755     auto nativeValue = LocalValueFromJsValue(map);
1756     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1757     panda::JsiFastNativeScope fastNativeScope(vm);
1758     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1759     if (LIKELY(nativeValue->IsMap(vm))) {
1760         Local<panda::MapRef> mapRef(nativeValue);
1761         Local<panda::ArrayRef> arrayVal = mapRef->GetValues(vm);
1762         *result = JsValueFromLocalValue(arrayVal);
1763     } else {
1764         Local<panda::SendableMapRef> mapRef(nativeValue);
1765         Local<panda::SendableArrayRef> arrayVal = mapRef->GetValues(vm);
1766         *result = JsValueFromLocalValue(arrayVal);
1767     }
1768     return GET_RETURN_STATUS(env);
1769 }
1770 
napi_map_iterator_get_next(napi_env env,napi_value iterator,napi_value * result)1771 NAPI_EXTERN napi_status napi_map_iterator_get_next(napi_env env, napi_value iterator, napi_value* result)
1772 {
1773     NAPI_PREAMBLE(env);
1774     CHECK_ARG(env, iterator);
1775     CHECK_ARG(env, result);
1776 
1777     auto nativeValue = LocalValueFromJsValue(iterator);
1778     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1779     panda::JsiFastNativeScope fastNativeScope(vm);
1780     RETURN_STATUS_IF_FALSE(env, nativeValue->IsMapIterator(vm) || nativeValue->IsSharedMapIterator(vm),
1781                            napi_object_expected);
1782     Local<panda::JSValueRef> value;
1783     if (LIKELY(nativeValue->IsMapIterator(vm))) {
1784         Local<panda::MapIteratorRef> mapIter(nativeValue);
1785         value = mapIter->Next(vm);
1786     } else {
1787         Local<panda::SendableMapIteratorRef> mapIter(nativeValue);
1788         value = mapIter->Next(vm);
1789     }
1790     *result = JsValueFromLocalValue(value);
1791     return GET_RETURN_STATUS(env);
1792 }
1793 
1794 // 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)1795 NAPI_EXTERN napi_status napi_wrap(napi_env env,
1796                                   napi_value js_object,
1797                                   void* native_object,
1798                                   napi_finalize finalize_cb,
1799                                   void* finalize_hint,
1800                                   napi_ref* result)
1801 {
1802     NAPI_PREAMBLE(env);
1803     CHECK_ARG(env, js_object);
1804     CHECK_ARG(env, native_object);
1805     CHECK_ARG(env, finalize_cb);
1806 
1807     auto nativeValue = LocalValueFromJsValue(js_object);
1808     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1809     auto engine = reinterpret_cast<NativeEngine*>(env);
1810     auto vm = engine->GetEcmaVm();
1811     panda::JsiFastNativeScope fastNativeScope(vm);
1812     CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1813     size_t nativeBindingSize = 0;
1814     auto reference = reinterpret_cast<NativeReference**>(result);
1815     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1816     if (native_object == nullptr && nativeObject->Has(vm, key)) {
1817         Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1818         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1819         // Try to remove native pointer from ArrayDataList
1820         wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, nativeBindingSize);
1821         nativeObject->Delete(vm, key);
1822         delete ref;
1823     } else {
1824         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1825         NativeReference* ref = nullptr;
1826         if (reference != nullptr) {
1827             ref = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
1828             *reference = ref;
1829         } else {
1830             ref = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
1831         }
1832         object->SetNativePointerFieldCount(vm, 1);
1833         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize);
1834         PropertyAttribute attr(object, true, false, true);
1835         nativeObject->DefineProperty(vm, key, attr);
1836     }
1837     return GET_RETURN_STATUS(env);
1838 }
1839 
1840 // 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)1841 NAPI_EXTERN napi_status napi_wrap_async_finalizer(napi_env env,
1842                                                   napi_value js_object,
1843                                                   void* native_object,
1844                                                   napi_finalize finalize_cb,
1845                                                   void* finalize_hint,
1846                                                   napi_ref* result,
1847                                                   size_t native_binding_size)
1848 {
1849     NAPI_PREAMBLE(env);
1850     CHECK_ARG(env, js_object);
1851     CHECK_ARG(env, native_object);
1852 
1853     auto nativeValue = LocalValueFromJsValue(js_object);
1854     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1855     auto engine = reinterpret_cast<NativeEngine*>(env);
1856     auto vm = engine->GetEcmaVm();
1857     panda::JsiFastNativeScope fastNativeScope(vm);
1858     CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1859     auto reference = reinterpret_cast<NativeReference**>(result);
1860     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1861     if (native_object == nullptr && nativeObject->Has(vm, key)) {
1862         Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1863         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1864         // Try to remove native pointer from ArrayDataList
1865         wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, native_binding_size);
1866         nativeObject->Delete(vm, key);
1867         delete ref;
1868     } else {
1869         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1870         NativeReference* ref = nullptr;
1871         if (reference != nullptr) {
1872             ref = engine->CreateAsyncReference(js_object, 1, false, callback, native_object, finalize_hint);
1873             *reference = ref;
1874         } else {
1875             ref = engine->CreateAsyncReference(js_object, 0, true, callback, native_object, finalize_hint);
1876         }
1877         object->SetNativePointerFieldCount(vm, 1);
1878         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, native_binding_size);
1879         PropertyAttribute attr(object, true, false, true);
1880         nativeObject->DefineProperty(vm, key, attr);
1881     }
1882     return GET_RETURN_STATUS(env);
1883 }
1884 
1885 // 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)1886 NAPI_EXTERN napi_status napi_wrap_with_size(napi_env env,
1887                                             napi_value js_object,
1888                                             void* native_object,
1889                                             napi_finalize finalize_cb,
1890                                             void* finalize_hint,
1891                                             napi_ref* result,
1892                                             size_t native_binding_size)
1893 {
1894     NAPI_PREAMBLE(env);
1895     CHECK_ARG(env, js_object);
1896     CHECK_ARG(env, native_object);
1897 
1898     auto nativeValue = LocalValueFromJsValue(js_object);
1899     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1900     auto engine = reinterpret_cast<NativeEngine*>(env);
1901     auto vm = engine->GetEcmaVm();
1902     panda::JsiFastNativeScope fastNativeScope(vm);
1903     CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1904     auto reference = reinterpret_cast<NativeReference**>(result);
1905     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1906     if (native_object == nullptr && nativeObject->Has(vm, key)) {
1907         Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1908         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1909         // Try to remove native pointer from ArrayDataList
1910         wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, native_binding_size);
1911         nativeObject->Delete(vm, key);
1912         delete ref;
1913     } else {
1914         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1915         NativeReference* ref = nullptr;
1916         if (reference != nullptr) {
1917             ref = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint,
1918                                           native_binding_size);
1919             *reference = ref;
1920         } else {
1921             ref = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint,
1922                                           native_binding_size);
1923         }
1924         object->SetNativePointerFieldCount(vm, 1);
1925         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, native_binding_size);
1926         PropertyAttribute attr(object, true, false, true);
1927         nativeObject->DefineProperty(vm, key, attr);
1928     }
1929 
1930     return GET_RETURN_STATUS(env);
1931 }
1932 
napi_unwrap(napi_env env,napi_value js_object,void ** result)1933 NAPI_EXTERN napi_status napi_unwrap(napi_env env, napi_value js_object, void** result)
1934 {
1935     NAPI_PREAMBLE(env);
1936     CHECK_ARG(env, js_object);
1937     CHECK_ARG(env, result);
1938 
1939     auto nativeValue = LocalValueFromJsValue(js_object);
1940     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1941     panda::JsiFastNativeScope fastNativeScope(vm);
1942     CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1943     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1944     Local<panda::JSValueRef> val = nativeObject->Get(vm, key);
1945     *result = nullptr;
1946     if (val->IsObject(vm)) {
1947         Local<panda::ObjectRef> ext(val);
1948         auto ref = reinterpret_cast<NativeReference*>(ext->GetNativePointerField(vm, 0));
1949         *result = ref != nullptr ? ref->GetData() : nullptr;
1950     }
1951 
1952     return GET_RETURN_STATUS(env);
1953 }
1954 
napi_remove_wrap(napi_env env,napi_value js_object,void ** result)1955 NAPI_EXTERN napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result)
1956 {
1957     NAPI_PREAMBLE(env);
1958     CHECK_ARG(env, js_object);
1959     CHECK_ARG(env, result);
1960 
1961     auto nativeValue = LocalValueFromJsValue(js_object);
1962     auto engine = reinterpret_cast<NativeEngine*>(env);
1963     auto vm = engine->GetEcmaVm();
1964     panda::JsiFastNativeScope fastNativeScope(vm);
1965     CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1966     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1967     Local<panda::JSValueRef> val = nativeObject->Get(vm, key);
1968     *result = nullptr;
1969     if (val->IsObject(vm)) {
1970         Local<panda::ObjectRef> ext(val);
1971         auto ref = reinterpret_cast<NativeReference*>(ext->GetNativePointerField(vm, 0));
1972         *result = ref != nullptr ? ref->GetData() : nullptr;
1973     }
1974 
1975     size_t nativeBindingSize = 0;
1976     if (nativeObject->Has(vm, key)) {
1977         Local<panda::ObjectRef> wrapper = val;
1978         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1979         nativeObject->Delete(vm, key);
1980         delete ref;
1981     } else {
1982         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1983         NativeReference* ref = nullptr;
1984         ref = engine->CreateReference(js_object, 0, true, nullptr, nullptr, nullptr);
1985         object->SetNativePointerFieldCount(vm, 1);
1986         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize);
1987         PropertyAttribute attr(object, true, false, true);
1988         nativeObject->DefineProperty(vm, key, attr);
1989     }
1990 
1991     return GET_RETURN_STATUS(env);
1992 }
1993 
napi_wrap_sendable(napi_env env,napi_value js_object,void * native_object,napi_finalize finalize_cb,void * finalize_hint)1994 NAPI_EXTERN napi_status napi_wrap_sendable(napi_env env,
1995                                            napi_value js_object,
1996                                            void* native_object,
1997                                            napi_finalize finalize_cb,
1998                                            void* finalize_hint)
1999 {
2000     NAPI_PREAMBLE(env);
2001     CHECK_ARG(env, js_object);
2002     CHECK_ARG(env, native_object);
2003 
2004     auto nativeValue = LocalValueFromJsValue(js_object);
2005     auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2006     auto engine = reinterpret_cast<NativeEngine*>(env);
2007     auto vm = engine->GetEcmaVm();
2008     panda::JsiFastNativeScope fastNativeScope(vm);
2009     RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2010     Local<ObjectRef> nativeObject(nativeValue);
2011     nativeObject->SetNativePointerFieldCount(vm, 1);
2012     nativeObject->SetNativePointerField(vm, 0, native_object, callback, finalize_hint);
2013     return GET_RETURN_STATUS(env);
2014 }
2015 
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)2016 NAPI_EXTERN napi_status napi_wrap_sendable_with_size(napi_env env,
2017                                                      napi_value js_object,
2018                                                      void* native_object,
2019                                                      napi_finalize finalize_cb,
2020                                                      void* finalize_hint,
2021                                                      size_t native_binding_size)
2022 {
2023     NAPI_PREAMBLE(env);
2024     CHECK_ARG(env, js_object);
2025     CHECK_ARG(env, native_object);
2026 
2027     auto nativeValue = LocalValueFromJsValue(js_object);
2028     auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2029     auto engine = reinterpret_cast<NativeEngine*>(env);
2030     auto vm = engine->GetEcmaVm();
2031     panda::JsiFastNativeScope fastNativeScope(vm);
2032     RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2033     Local<ObjectRef> nativeObject(nativeValue);
2034     nativeObject->SetNativePointerFieldCount(vm, 1);
2035     nativeObject->SetNativePointerField(vm, 0, native_object, callback, finalize_hint, native_binding_size);
2036     return GET_RETURN_STATUS(env);
2037 }
2038 
napi_unwrap_sendable(napi_env env,napi_value js_object,void ** result)2039 NAPI_EXTERN napi_status napi_unwrap_sendable(napi_env env, napi_value js_object, void** result)
2040 {
2041     NAPI_PREAMBLE(env);
2042     CHECK_ARG(env, js_object);
2043     CHECK_ARG(env, result);
2044 
2045     auto nativeValue = LocalValueFromJsValue(js_object);
2046     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2047     panda::JsiFastNativeScope fastNativeScope(vm);
2048     RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2049     Local<ObjectRef> nativeObject(nativeValue);
2050     void* val = nativeObject->GetNativePointerField(vm, 0);
2051     *result = val;
2052     return GET_RETURN_STATUS(env);
2053 }
2054 
napi_remove_wrap_sendable(napi_env env,napi_value js_object,void ** result)2055 NAPI_EXTERN napi_status napi_remove_wrap_sendable(napi_env env, napi_value js_object, void** result)
2056 {
2057     NAPI_PREAMBLE(env);
2058     CHECK_ARG(env, js_object);
2059     CHECK_ARG(env, result);
2060 
2061     auto nativeValue = LocalValueFromJsValue(js_object);
2062     auto engine = reinterpret_cast<NativeEngine*>(env);
2063     auto vm = engine->GetEcmaVm();
2064     panda::JsiFastNativeScope fastNativeScope(vm);
2065     RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2066     Local<ObjectRef> nativeObject(nativeValue);
2067     void* val = nativeObject->GetNativePointerField(vm, 0);
2068     *result = val;
2069     nativeObject->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr);
2070 
2071     return GET_RETURN_STATUS(env);
2072 }
2073 
napi_create_external(napi_env env,void * data,napi_finalize finalize_cb,void * finalize_hint,napi_value * result)2074 NAPI_EXTERN napi_status napi_create_external(
2075     napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint, napi_value* result)
2076 {
2077     NAPI_PREAMBLE(env);
2078     CHECK_ARG(env, result);
2079 
2080     auto engine = reinterpret_cast<NativeEngine*>(env);
2081     auto vm = engine->GetEcmaVm();
2082     auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2083     Local<panda::NativePointerRef> object = panda::NativePointerRef::New(vm, data, callback, finalize_hint, 0);
2084 
2085     *result = JsValueFromLocalValue(object);
2086     return napi_clear_last_error(env);
2087 }
2088 
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)2089 NAPI_EXTERN napi_status napi_create_external_with_size(napi_env env,
2090                                                        void* data,
2091                                                        napi_finalize finalize_cb,
2092                                                        void* finalize_hint,
2093                                                        napi_value* result,
2094                                                        size_t native_binding_size)
2095 {
2096     CHECK_ENV(env);
2097     CHECK_ARG(env, result);
2098 
2099     auto engine = reinterpret_cast<NativeEngine*>(env);
2100     auto vm = engine->GetEcmaVm();
2101     auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2102     Local<panda::NativePointerRef> object =
2103         panda::NativePointerRef::New(vm, data, callback, finalize_hint, native_binding_size);
2104 
2105     *result = JsValueFromLocalValue(object);
2106     return napi_clear_last_error(env);
2107 }
2108 
napi_get_value_external(napi_env env,napi_value value,void ** result)2109 NAPI_EXTERN napi_status napi_get_value_external(napi_env env, napi_value value, void** result)
2110 {
2111     CHECK_ENV(env);
2112     CHECK_ARG(env, value);
2113     CHECK_ARG(env, result);
2114 
2115     auto nativeValue = LocalValueFromJsValue(value);
2116     bool isNativePointer = false;
2117     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2118     void* ret = nativeValue->GetNativePointerValue(vm, isNativePointer);
2119     RETURN_STATUS_IF_FALSE(env, isNativePointer, napi_object_expected);
2120     *result = ret;
2121     return napi_clear_last_error(env);
2122 }
2123 
2124 // Methods to control object lifespan
2125 // 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)2126 NAPI_EXTERN napi_status napi_create_reference(napi_env env,
2127                                               napi_value value,
2128                                               uint32_t initial_refcount,
2129                                               napi_ref* result)
2130 {
2131     CHECK_ENV(env);
2132     CHECK_ARG(env, value);
2133     CHECK_ARG(env, result);
2134     auto engine = reinterpret_cast<ArkNativeEngine*>(env);
2135     auto ref = new ArkNativeReference(engine, value, initial_refcount);
2136 
2137     *result = reinterpret_cast<napi_ref>(ref);
2138     return napi_clear_last_error(env);
2139 }
2140 
2141 // Deletes a reference. The referenced value is released, and may
2142 // be GC'd unless there are other references to it.
napi_delete_reference(napi_env env,napi_ref ref)2143 NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref)
2144 {
2145     CHECK_ENV(env);
2146     CHECK_ARG(env, ref);
2147 
2148     auto reference = reinterpret_cast<NativeReference*>(ref);
2149     uint32_t refCount = reference->GetRefCount();
2150     if (refCount > 0 || reference->GetFinalRun()) {
2151         delete reference;
2152         reference = nullptr;
2153     } else {
2154         reference->SetDeleteSelf();
2155     }
2156 
2157     return napi_clear_last_error(env);
2158 }
2159 
2160 // Increments the reference count, optionally returning the resulting count.
2161 // After this call the  reference will be a strong reference because its
2162 // refcount is >0, and the referenced object is effectively "pinned".
2163 // Calling this when the refcount is 0 and the object is unavailable
2164 // results in an error.
napi_reference_ref(napi_env env,napi_ref ref,uint32_t * result)2165 NAPI_EXTERN napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result)
2166 {
2167     CHECK_ENV(env);
2168     CHECK_ARG(env, ref);
2169 
2170     auto reference = reinterpret_cast<NativeReference*>(ref);
2171     uint32_t refCount = reference->Ref();
2172 
2173     if (result) {
2174         *result = refCount;
2175     }
2176 
2177     return napi_clear_last_error(env);
2178 }
2179 
2180 // Decrements the reference count, optionally returning the resulting count.
2181 // If the result is 0 the reference is now weak and the object may be GC'd
2182 // at any time if there are no other references. Calling this when the
2183 // refcount is already 0 results in an error.
napi_reference_unref(napi_env env,napi_ref ref,uint32_t * result)2184 NAPI_EXTERN napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result)
2185 {
2186     CHECK_ENV(env);
2187     CHECK_ARG(env, ref);
2188 
2189     auto reference = reinterpret_cast<NativeReference*>(ref);
2190     uint32_t unrefCount = reference->Unref();
2191 
2192     if (result) {
2193         *result = unrefCount;
2194     }
2195 
2196     return napi_clear_last_error(env);
2197 }
2198 
2199 // Attempts to get a referenced value. If the reference is weak,
2200 // the value might no longer be available, in that case the call
2201 // is still successful but the result is nullptr.
napi_get_reference_value(napi_env env,napi_ref ref,napi_value * result)2202 NAPI_EXTERN napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result)
2203 {
2204     CHECK_ENV(env);
2205     CHECK_ARG(env, ref);
2206     CHECK_ARG(env, result);
2207 
2208     auto reference = reinterpret_cast<NativeReference*>(ref);
2209     NativeEngine* engine = reinterpret_cast<NativeEngine*>(env);
2210 
2211     *result = reference->Get(engine);
2212     return napi_clear_last_error(env);
2213 }
2214 
napi_open_handle_scope(napi_env env,napi_handle_scope * result)2215 NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result)
2216 {
2217     CHECK_ENV(env);
2218     CHECK_ARG(env, result);
2219 
2220     auto engine = reinterpret_cast<NativeEngine*>(env);
2221     *result = HandleScopeToNapiHandleScope(new HandleScopeWrapper(engine));
2222     engine->openHandleScopes_++;
2223     return napi_clear_last_error(env);
2224 }
2225 
napi_close_handle_scope(napi_env env,napi_handle_scope scope)2226 NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope)
2227 {
2228     CHECK_ENV(env);
2229     CHECK_ARG(env, scope);
2230 
2231     auto engine = reinterpret_cast<NativeEngine*>(env);
2232     if (engine->openHandleScopes_ == 0) {
2233         return napi_handle_scope_mismatch;
2234     }
2235 
2236     engine->openHandleScopes_--;
2237     delete NapiHandleScopeToHandleScope(scope);
2238     return napi_clear_last_error(env);
2239 }
2240 
napi_open_escapable_handle_scope(napi_env env,napi_escapable_handle_scope * result)2241 NAPI_EXTERN napi_status napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle_scope* result)
2242 {
2243     CHECK_ENV(env);
2244     CHECK_ARG(env, result);
2245 
2246     auto engine = reinterpret_cast<NativeEngine*>(env);
2247     *result = EscapableHandleScopeToNapiEscapableHandleScope(new EscapableHandleScopeWrapper(engine));
2248     engine->openHandleScopes_++;
2249     return napi_clear_last_error(env);
2250 }
2251 
napi_close_escapable_handle_scope(napi_env env,napi_escapable_handle_scope scope)2252 NAPI_EXTERN napi_status napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope scope)
2253 {
2254     CHECK_ENV(env);
2255     CHECK_ARG(env, scope);
2256 
2257     auto engine = reinterpret_cast<NativeEngine*>(env);
2258     if (engine->openHandleScopes_ == 0) {
2259         return napi_handle_scope_mismatch;
2260     }
2261 
2262     engine->openHandleScopes_--;
2263     delete NapiEscapableHandleScopeToEscapableHandleScope(scope);
2264     return napi_clear_last_error(env);
2265 }
2266 
napi_escape_handle(napi_env env,napi_escapable_handle_scope scope,napi_value escapee,napi_value * result)2267 NAPI_EXTERN napi_status napi_escape_handle(napi_env env,
2268                                            napi_escapable_handle_scope scope,
2269                                            napi_value escapee,
2270                                            napi_value* result)
2271 {
2272     CHECK_ENV(env);
2273     CHECK_ARG(env, scope);
2274     CHECK_ARG(env, escapee);
2275     CHECK_ARG(env, result);
2276 
2277     auto s = NapiEscapableHandleScopeToEscapableHandleScope(scope);
2278     if (!s->IsEscapeCalled()) {
2279         *result = JsValueFromLocalValue(s->Escape(LocalValueFromJsValue(escapee)));
2280         return napi_clear_last_error(env);
2281     }
2282     return napi_set_last_error(env, napi_escape_called_twice);
2283 }
2284 
2285 // Methods to support error handling
napi_throw(napi_env env,napi_value error)2286 NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error)
2287 {
2288     CHECK_ENV(env);
2289     CHECK_ARG(env, error);
2290 
2291     auto nativeValue = LocalValueFromJsValue(error);
2292     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2293     panda::JsiFastNativeScope fastNativeScope(vm);
2294 
2295     RETURN_STATUS_IF_FALSE(env, nativeValue->IsError(vm), napi_invalid_arg);
2296     panda::JSNApi::ThrowException(vm, nativeValue);
2297     return napi_clear_last_error(env);
2298 }
2299 
napi_throw_error(napi_env env,const char * code,const char * msg)2300 NAPI_EXTERN napi_status napi_throw_error(napi_env env, const char* code, const char* msg)
2301 {
2302     CHECK_ENV(env);
2303     CHECK_ARG(env, msg);
2304 
2305     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2306     panda::JsiFastNativeScope fastNativeScope(vm);
2307     Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
2308     error = panda::Exception::Error(vm, StringRef::NewFromUtf8(vm, msg));
2309     if (code != nullptr) {
2310         Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
2311         Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
2312         Local<panda::ObjectRef> errorObj(error);
2313         errorObj->Set(vm, codeKey, codeValue);
2314     }
2315     panda::JSNApi::ThrowException(vm, error);
2316     return napi_clear_last_error(env);
2317 }
2318 
napi_throw_type_error(napi_env env,const char * code,const char * msg)2319 NAPI_EXTERN napi_status napi_throw_type_error(napi_env env, const char* code, const char* msg)
2320 {
2321     CHECK_ENV(env);
2322     CHECK_ARG(env, msg);
2323 
2324     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2325     panda::JsiFastNativeScope fastNativeScope(vm);
2326     Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
2327     error = panda::Exception::TypeError(vm, StringRef::NewFromUtf8(vm, msg));
2328     if (code != nullptr) {
2329         Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
2330         Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
2331         Local<panda::ObjectRef> errorObj(error);
2332         errorObj->Set(vm, codeKey, codeValue);
2333     }
2334     panda::JSNApi::ThrowException(vm, error);
2335     return napi_clear_last_error(env);
2336 }
2337 
napi_throw_range_error(napi_env env,const char * code,const char * msg)2338 NAPI_EXTERN napi_status napi_throw_range_error(napi_env env, const char* code, const char* msg)
2339 {
2340     CHECK_ENV(env);
2341     CHECK_ARG(env, msg);
2342 
2343     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2344     panda::JsiFastNativeScope fastNativeScope(vm);
2345     Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
2346     error = panda::Exception::RangeError(vm, StringRef::NewFromUtf8(vm, msg));
2347     if (code != nullptr) {
2348         Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
2349         Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
2350         Local<panda::ObjectRef> errorObj(error);
2351         errorObj->Set(vm, codeKey, codeValue);
2352     }
2353     panda::JSNApi::ThrowException(vm, error);
2354     return napi_clear_last_error(env);
2355 }
2356 
napi_is_error(napi_env env,napi_value value,bool * result)2357 NAPI_EXTERN napi_status napi_is_error(napi_env env, napi_value value, bool* result)
2358 {
2359     CHECK_ENV(env);
2360     CHECK_ARG(env, value);
2361     CHECK_ARG(env, result);
2362 
2363     auto nativeValue = LocalValueFromJsValue(value);
2364     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2365     panda::JsiFastNativeScope fastNativeScope(vm);
2366     *result = nativeValue->IsError(vm);
2367 
2368     return napi_clear_last_error(env);
2369 }
2370 
2371 // Methods to support catching exceptions
napi_is_exception_pending(napi_env env,bool * result)2372 NAPI_EXTERN napi_status napi_is_exception_pending(napi_env env, bool* result)
2373 {
2374     CHECK_ENV(env);
2375     CHECK_ARG(env, result);
2376 
2377     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2378     *result = panda::JSNApi::HasPendingException(vm);
2379     return napi_clear_last_error(env);
2380 }
2381 
napi_get_and_clear_last_exception(napi_env env,napi_value * result)2382 NAPI_EXTERN napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result)
2383 {
2384     CHECK_ENV(env);
2385     CHECK_ARG(env, result);
2386 
2387     auto engine = reinterpret_cast<NativeEngine*>(env);
2388     auto vm = engine->GetEcmaVm();
2389     engine->lastException_.Empty();
2390     Local<panda::ObjectRef> exception = panda::JSNApi::GetAndClearUncaughtException(vm);
2391     if (!exception.IsNull()) {
2392         *result = JsValueFromLocalValue(exception);
2393     }
2394 
2395     return napi_clear_last_error(env);
2396 }
2397 
2398 // Methods to work with array buffers and typed arrays
napi_is_arraybuffer(napi_env env,napi_value value,bool * result)2399 NAPI_EXTERN napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result)
2400 {
2401     CHECK_ENV(env);
2402     CHECK_ARG(env, value);
2403     CHECK_ARG(env, result);
2404 
2405     auto nativeValue = LocalValueFromJsValue(value);
2406     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2407     panda::JsiFastNativeScope fastNativeScope(vm);
2408 
2409     *result = nativeValue->IsArrayBuffer(vm) || nativeValue->IsSendableArrayBuffer(vm);
2410 
2411     return napi_clear_last_error(env);
2412 }
2413 
napi_create_arraybuffer(napi_env env,size_t byte_length,void ** data,napi_value * result)2414 NAPI_EXTERN napi_status napi_create_arraybuffer(napi_env env, size_t byte_length, void** data, napi_value* result)
2415 {
2416     NAPI_PREAMBLE(env);
2417     CHECK_ARG(env, data);
2418     CHECK_ARG(env, result);
2419 
2420     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2421     uint8_t** values = (uint8_t**)(data);
2422     Local<panda::ArrayBufferRef> res = panda::ArrayBufferRef::New(vm, byte_length);
2423     if (values != nullptr) {
2424         *values = reinterpret_cast<uint8_t*>(res->GetBuffer(vm));
2425     }
2426     *result = JsValueFromLocalValue(res);
2427 
2428     return GET_RETURN_STATUS(env);
2429 }
2430 
napi_create_sendable_arraybuffer(napi_env env,size_t byte_length,void ** data,napi_value * result)2431 NAPI_EXTERN napi_status napi_create_sendable_arraybuffer(napi_env env, size_t byte_length,
2432                                                          void** data, napi_value* result)
2433 {
2434     NAPI_PREAMBLE(env);
2435     CHECK_ARG(env, data);
2436     CHECK_ARG(env, result);
2437 
2438     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2439     uint8_t** values = (uint8_t**)(data);
2440     Local<panda::SendableArrayBufferRef> res = panda::SendableArrayBufferRef::New(vm, byte_length);
2441     if (values != nullptr) {
2442         *values = reinterpret_cast<uint8_t*>(res->GetBuffer(vm));
2443     }
2444     *result = JsValueFromLocalValue(res);
2445 
2446     return GET_RETURN_STATUS(env);
2447 }
2448 
napi_create_external_arraybuffer(napi_env env,void * external_data,size_t byte_length,napi_finalize finalize_cb,void * finalize_hint,napi_value * result)2449 NAPI_EXTERN napi_status napi_create_external_arraybuffer(napi_env env,
2450                                                          void* external_data,
2451                                                          size_t byte_length,
2452                                                          napi_finalize finalize_cb,
2453                                                          void* finalize_hint,
2454                                                          napi_value* result)
2455 {
2456     NAPI_PREAMBLE(env);
2457     CHECK_ARG(env, external_data);
2458     CHECK_ARG(env, finalize_cb);
2459     CHECK_ARG(env, result);
2460 
2461     auto engine = reinterpret_cast<NativeEngine*>(env);
2462     auto vm = engine->GetEcmaVm();
2463     auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2464     Local<panda::ArrayBufferRef> object =
2465         panda::ArrayBufferRef::New(vm, external_data, byte_length, callback, finalize_hint);
2466     *result = JsValueFromLocalValue(object);
2467     return GET_RETURN_STATUS(env);
2468 }
2469 
napi_get_arraybuffer_info(napi_env env,napi_value arraybuffer,void ** data,size_t * byte_length)2470 NAPI_EXTERN napi_status napi_get_arraybuffer_info(napi_env env,
2471                                                   napi_value arraybuffer,
2472                                                   void** data,
2473                                                   size_t* byte_length)
2474 {
2475     CHECK_ENV(env);
2476     CHECK_ARG(env, arraybuffer);
2477     CHECK_ARG(env, byte_length);
2478 
2479     auto nativeValue = LocalValueFromJsValue(arraybuffer);
2480     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2481     panda::JsiFastNativeScope fastNativeScope(vm);
2482     if (LIKELY(nativeValue->IsArrayBuffer(vm))) {
2483         Local<panda::ArrayBufferRef> res(nativeValue);
2484         if (data != nullptr) {
2485             *data = res->GetBuffer(vm);
2486         }
2487         *byte_length = res->ByteLength(vm);
2488     } else if (nativeValue->IsSendableArrayBuffer(vm)) {
2489         Local<panda::SendableArrayBufferRef> res(nativeValue);
2490         if (data != nullptr) {
2491             *data = res->GetBuffer(vm);
2492         }
2493         *byte_length = res->ByteLength(vm);
2494     } else {
2495         return napi_set_last_error(env, napi_arraybuffer_expected);
2496     }
2497 
2498     return napi_clear_last_error(env);
2499 }
2500 
napi_is_typedarray(napi_env env,napi_value value,bool * result)2501 NAPI_EXTERN napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result)
2502 {
2503     CHECK_ENV(env);
2504     CHECK_ARG(env, value);
2505     CHECK_ARG(env, result);
2506 
2507     auto nativeValue = LocalValueFromJsValue(value);
2508     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2509     panda::JsiFastNativeScope fastNativeScope(vm);
2510 
2511     *result = nativeValue->IsTypedArray(vm) || nativeValue->IsSharedTypedArray(vm);
2512 
2513     return napi_clear_last_error(env);
2514 }
2515 
2516 EXTERN_C_START
napi_is_buffer(napi_env env,napi_value value,bool * result)2517 NAPI_EXTERN napi_status napi_is_buffer(napi_env env, napi_value value, bool* result)
2518 {
2519     CHECK_ENV(env);
2520     CHECK_ARG(env, value);
2521     CHECK_ARG(env, result);
2522 
2523     auto nativeValue = LocalValueFromJsValue(value);
2524     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2525     panda::JsiFastNativeScope fastNativeScope(vm);
2526 
2527     *result = nativeValue->IsBuffer(vm);
2528 
2529     return napi_clear_last_error(env);
2530 }
2531 
napi_create_buffer(napi_env env,size_t size,void ** data,napi_value * result)2532 NAPI_EXTERN napi_status napi_create_buffer(napi_env env, size_t size, void** data, napi_value* result)
2533 {
2534     CHECK_ENV(env);
2535     CHECK_ARG(env, data);
2536     CHECK_ARG(env, result);
2537     RETURN_STATUS_IF_FALSE(env, size > 0, napi_invalid_arg);
2538 
2539     uint8_t** value =  reinterpret_cast<uint8_t**>(data);
2540     if (!value) {
2541         HILOG_ERROR("value is empty");
2542         return napi_set_last_error(env, napi_invalid_arg);
2543     }
2544 
2545     if (size > MAX_BYTE_LENGTH) {
2546         HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
2547                     static_cast<float>(size) / static_cast<float>(ONEMIB_BYTE_SIZE),
2548                     static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
2549         *value = nullptr;
2550         return napi_set_last_error(env, napi_invalid_arg);
2551     }
2552     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2553     Local<panda::BufferRef> obj = BufferRef::New(vm, size);
2554     *value = reinterpret_cast<uint8_t*>(obj->GetBuffer(vm));
2555 
2556     CHECK_ARG(env, *data);
2557     void* ptr = obj->GetBuffer(vm);
2558     CHECK_ARG(env, ptr);
2559 
2560     *result = JsValueFromLocalValue(obj);
2561     return napi_clear_last_error(env);
2562 }
2563 
napi_create_buffer_copy(napi_env env,size_t length,const void * data,void ** result_data,napi_value * result)2564 NAPI_EXTERN napi_status napi_create_buffer_copy(napi_env env,
2565                                                 size_t length,
2566                                                 const void* data,
2567                                                 void** result_data,
2568                                                 napi_value* result)
2569 {
2570     CHECK_ENV(env);
2571     CHECK_ARG(env, data);
2572     CHECK_ARG(env, result_data);
2573     CHECK_ARG(env, result);
2574     RETURN_STATUS_IF_FALSE(env, length > 0, napi_invalid_arg);
2575 
2576     uint8_t** value = reinterpret_cast<uint8_t**>(result_data);
2577     const uint8_t* recvdata = (uint8_t*)data;
2578     if (!value) {
2579         HILOG_ERROR("value is empty");
2580         return napi_set_last_error(env, napi_invalid_arg);
2581     }
2582     if (length > MAX_BYTE_LENGTH) {
2583         HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
2584                     static_cast<float>(length) / static_cast<float>(ONEMIB_BYTE_SIZE),
2585                     static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
2586         *value = nullptr;
2587         return napi_set_last_error(env, napi_invalid_arg);
2588     }
2589     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2590     Local<panda::BufferRef> obj = BufferRef::New(vm, length);
2591     if (obj->IsUndefined()) {
2592         HILOG_INFO("engine create buffer_copy failed!");
2593     }
2594     *value = reinterpret_cast<uint8_t*>(obj->GetBuffer(vm));
2595     if (memcpy_s(*value, length, recvdata, length) != EOK) {
2596         HILOG_ERROR("memcpy_s failed");
2597     }
2598 
2599     void* ptr = obj->GetBuffer(vm);
2600     CHECK_ARG(env, ptr);
2601 
2602     *result = JsValueFromLocalValue(obj);
2603     return napi_clear_last_error(env);
2604 }
2605 
napi_create_external_buffer(napi_env env,size_t length,void * data,napi_finalize finalize_cb,void * finalize_hint,napi_value * result)2606 NAPI_EXTERN napi_status napi_create_external_buffer(napi_env env,
2607                                                     size_t length,
2608                                                     void* data,
2609                                                     napi_finalize finalize_cb,
2610                                                     void* finalize_hint,
2611                                                     napi_value* result)
2612 {
2613     NAPI_PREAMBLE(env);
2614     CHECK_ARG(env, result);
2615     CHECK_ARG(env, data);
2616     RETURN_STATUS_IF_FALSE(env, length > 0, napi_invalid_arg);
2617 
2618     auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2619     if (!data) {
2620         HILOG_ERROR("data is empty");
2621         return napi_set_last_error(env, napi_invalid_arg);
2622     }
2623     if (length > MAX_BYTE_LENGTH) {
2624         HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
2625                     static_cast<float>(length) / static_cast<float>(ONEMIB_BYTE_SIZE),
2626                     static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
2627         data = nullptr;
2628         return napi_set_last_error(env, napi_invalid_arg);
2629     }
2630 
2631     auto engine = reinterpret_cast<NativeEngine*>(env);
2632     auto vm = engine->GetEcmaVm();
2633     Local<panda::BufferRef> object = panda::BufferRef::New(vm, data, length, callback, finalize_hint);
2634     void* ptr = object->GetBuffer(vm);
2635     CHECK_ARG(env, ptr);
2636 
2637     *result = JsValueFromLocalValue(object);
2638     return GET_RETURN_STATUS(env);
2639 }
2640 
napi_get_buffer_info(napi_env env,napi_value value,void ** data,size_t * length)2641 NAPI_EXTERN napi_status napi_get_buffer_info(napi_env env, napi_value value, void** data, size_t* length)
2642 {
2643     CHECK_ENV(env);
2644     CHECK_ARG(env, value);
2645 
2646     auto nativeValue = LocalValueFromJsValue(value);
2647     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2648     panda::JsiFastNativeScope fastNativeScope(vm);
2649     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBuffer(vm), napi_status::napi_arraybuffer_expected);
2650     Local<panda::BufferRef> res(nativeValue);
2651     *data = res->GetBuffer(vm);
2652     *length = res->ByteLength(vm);
2653 
2654     return napi_clear_last_error(env);
2655 }
2656 
napi_object_freeze(napi_env env,napi_value object)2657 NAPI_EXTERN napi_status napi_object_freeze(napi_env env, napi_value object)
2658 {
2659     NAPI_PREAMBLE(env);
2660     CHECK_ARG(env, object);
2661 
2662     auto nativeValue = LocalValueFromJsValue(object);
2663     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2664     panda::JsiFastNativeScope fastNativeScope(vm);
2665     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
2666     Local<panda::ObjectRef> obj = nativeValue->ToEcmaObject(vm);
2667     obj->Freeze(vm);
2668 
2669     return GET_RETURN_STATUS(env);
2670 }
2671 
napi_object_seal(napi_env env,napi_value object)2672 NAPI_EXTERN napi_status napi_object_seal(napi_env env, napi_value object)
2673 {
2674     NAPI_PREAMBLE(env);
2675     CHECK_ARG(env, object);
2676 
2677     auto nativeValue = LocalValueFromJsValue(object);
2678     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2679     panda::JsiFastNativeScope fastNativeScope(vm);
2680     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
2681     Local<panda::ObjectRef> obj = nativeValue->ToEcmaObject(vm);
2682     obj->Seal(vm);
2683 
2684     return GET_RETURN_STATUS(env);
2685 }
2686 
2687 EXTERN_C_END
2688 
napi_create_typedarray(napi_env env,napi_typedarray_type type,size_t length,napi_value arraybuffer,size_t byte_offset,napi_value * result)2689 NAPI_EXTERN napi_status napi_create_typedarray(napi_env env,
2690                                                napi_typedarray_type type,
2691                                                size_t length,
2692                                                napi_value arraybuffer,
2693                                                size_t byte_offset,
2694                                                napi_value* result)
2695 {
2696     NAPI_PREAMBLE(env);
2697     CHECK_ARG(env, arraybuffer);
2698     CHECK_ARG(env, result);
2699 
2700     auto value = LocalValueFromJsValue(arraybuffer);
2701     auto typedArrayType = (NativeTypedArrayType)type;
2702     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2703     panda::JsiFastNativeScope fastNativeScope(vm);
2704     RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(vm), napi_status::napi_arraybuffer_expected);
2705     Local<panda::ArrayBufferRef> arrayBuf(value);
2706 
2707     if (!reinterpret_cast<NativeEngine*>(env)->NapiNewTypedArray(vm, typedArrayType, arrayBuf,
2708                                                                  byte_offset, length, result)) {
2709         HILOG_ERROR("%{public}s invalid arg", __func__);
2710         return napi_set_last_error(env, napi_invalid_arg);
2711     }
2712     return GET_RETURN_STATUS(env);
2713 }
2714 
napi_create_sendable_typedarray(napi_env env,napi_typedarray_type type,size_t length,napi_value arraybuffer,size_t byte_offset,napi_value * result)2715 NAPI_EXTERN napi_status napi_create_sendable_typedarray(napi_env env,
2716                                                         napi_typedarray_type type,
2717                                                         size_t length,
2718                                                         napi_value arraybuffer,
2719                                                         size_t byte_offset,
2720                                                         napi_value* result)
2721 {
2722     NAPI_PREAMBLE(env);
2723     CHECK_ARG(env, arraybuffer);
2724     CHECK_ARG(env, result);
2725 
2726     auto value = LocalValueFromJsValue(arraybuffer);
2727     auto typedArrayType = (NativeTypedArrayType)type;
2728     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2729     panda::JsiFastNativeScope fastNativeScope(vm);
2730     RETURN_STATUS_IF_FALSE(env, value->IsSendableArrayBuffer(vm), napi_status::napi_arraybuffer_expected);
2731     Local<panda::SendableArrayBufferRef> arrayBuf(value);
2732 
2733     if (!reinterpret_cast<NativeEngine*>(env)->NapiNewSendableTypedArray(vm, typedArrayType,
2734                                                                          arrayBuf, byte_offset,
2735                                                                          length, result)) {
2736         HILOG_ERROR("%{public}s invalid arg", __func__);
2737         return napi_set_last_error(env, napi_invalid_arg);
2738     }
2739     return GET_RETURN_STATUS(env);
2740 }
2741 
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)2742 NAPI_EXTERN napi_status napi_get_typedarray_info(napi_env env,
2743                                                  napi_value typedarray,
2744                                                  napi_typedarray_type* type,
2745                                                  size_t* length,
2746                                                  void** data,
2747                                                  napi_value* arraybuffer,
2748                                                  size_t* byte_offset)
2749 {
2750     CHECK_ENV(env);
2751     CHECK_ARG(env, typedarray);
2752 
2753     auto value = LocalValueFromJsValue(typedarray);
2754     auto engine = reinterpret_cast<NativeEngine*>(env);
2755     auto vm = engine->GetEcmaVm();
2756     panda::JsiFastNativeScope fastNativeScope(vm);
2757     if (LIKELY(value->IsTypedArray(vm))) {
2758         Local<panda::TypedArrayRef> typedArray = Local<panda::TypedArrayRef>(value);
2759         if (type != nullptr) {
2760             *type = static_cast<napi_typedarray_type>(engine->GetTypedArrayType(typedArray));
2761         }
2762         if (length != nullptr) {
2763             *length = typedArray->ByteLength(vm);
2764         }
2765         if (data != nullptr) {
2766             *data = static_cast<uint8_t*>(typedArray->GetArrayBuffer(vm)->GetBuffer(vm)) + typedArray->ByteOffset(vm);
2767         }
2768         if (arraybuffer != nullptr) {
2769             *arraybuffer = JsValueFromLocalValue(typedArray->GetArrayBuffer(vm));
2770         }
2771         if (byte_offset != nullptr) {
2772             *byte_offset = typedArray->ByteOffset(vm);
2773         }
2774     } else if (value->IsSharedTypedArray(vm)) {
2775         Local<panda::SendableTypedArrayRef> typedArray = Local<panda::SendableTypedArrayRef>(value);
2776         if (type != nullptr) {
2777             *type = static_cast<napi_typedarray_type>(engine->GetSendableTypedArrayType(typedArray));
2778         }
2779         if (length != nullptr) {
2780             *length = typedArray->ByteLength(vm);
2781         }
2782         if (data != nullptr) {
2783             *data = static_cast<uint8_t*>(typedArray->GetArrayBuffer(vm)->GetBuffer(vm)) + typedArray->ByteOffset(vm);
2784         }
2785         if (arraybuffer != nullptr) {
2786             *arraybuffer = JsValueFromLocalValue(typedArray->GetArrayBuffer(vm));
2787         }
2788         if (byte_offset != nullptr) {
2789             *byte_offset = typedArray->ByteOffset(vm);
2790         }
2791     } else {
2792         HILOG_ERROR("%{public}s invalid arg", __func__);
2793         return napi_set_last_error(env, napi_invalid_arg);
2794     }
2795 
2796     return napi_clear_last_error(env);
2797 }
2798 
napi_create_dataview(napi_env env,size_t length,napi_value arraybuffer,size_t byte_offset,napi_value * result)2799 NAPI_EXTERN napi_status napi_create_dataview(napi_env env,
2800                                              size_t length,
2801                                              napi_value arraybuffer,
2802                                              size_t byte_offset,
2803                                              napi_value* result)
2804 {
2805     NAPI_PREAMBLE(env);
2806     CHECK_ARG(env, arraybuffer);
2807     CHECK_ARG(env, result);
2808 
2809     auto arrayBufferValue = LocalValueFromJsValue(arraybuffer);
2810     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2811     panda::JsiFastNativeScope fastNativeScope(vm);
2812     RETURN_STATUS_IF_FALSE(env, arrayBufferValue->IsArrayBuffer(vm), napi_status::napi_arraybuffer_expected);
2813     Local<panda::ArrayBufferRef> res(arrayBufferValue);
2814     if (length + byte_offset > static_cast<size_t>(res->ByteLength(vm))) {
2815         napi_throw_range_error(
2816             env,
2817             "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2818             "byte_offset + byte_length should be less than or "
2819             "equal to the size in bytes of the array passed in");
2820         return napi_set_last_error(env, napi_pending_exception);
2821     }
2822 
2823     Local<panda::DataViewRef> dataView = panda::DataViewRef::New(vm, res, byte_offset, length);
2824     *result = JsValueFromLocalValue(dataView);
2825     return GET_RETURN_STATUS(env);
2826 }
2827 
napi_is_dataview(napi_env env,napi_value value,bool * result)2828 NAPI_EXTERN napi_status napi_is_dataview(napi_env env, napi_value value, bool* result)
2829 {
2830     CHECK_ENV(env);
2831     CHECK_ARG(env, value);
2832     CHECK_ARG(env, result);
2833 
2834     auto nativeValue = LocalValueFromJsValue(value);
2835     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2836     panda::JsiFastNativeScope fastNativeScope(vm);
2837     *result = nativeValue->IsDataView(vm);
2838 
2839     return napi_clear_last_error(env);
2840 }
2841 
napi_get_dataview_info(napi_env env,napi_value dataview,size_t * bytelength,void ** data,napi_value * arraybuffer,size_t * byte_offset)2842 NAPI_EXTERN napi_status napi_get_dataview_info(napi_env env,
2843                                                napi_value dataview,
2844                                                size_t* bytelength,
2845                                                void** data,
2846                                                napi_value* arraybuffer,
2847                                                size_t* byte_offset)
2848 {
2849     CHECK_ENV(env);
2850     CHECK_ARG(env, dataview);
2851 
2852     auto nativeValue = LocalValueFromJsValue(dataview);
2853     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2854     bool isDataView = false;
2855     nativeValue->GetDataViewInfo(vm, isDataView, bytelength, data,
2856         reinterpret_cast<panda::JSValueRef**>(arraybuffer), byte_offset);
2857     RETURN_STATUS_IF_FALSE(env, isDataView, napi_status::napi_invalid_arg);
2858 
2859     return napi_clear_last_error(env);
2860 }
2861 
2862 // version management
napi_get_version(napi_env env,uint32_t * result)2863 NAPI_EXTERN napi_status napi_get_version(napi_env env, uint32_t* result)
2864 {
2865     CHECK_ENV(env);
2866     CHECK_ARG(env, result);
2867 
2868     *result = NAPI_VERSION;
2869     return napi_clear_last_error(env);
2870 }
2871 
2872 // Promises
napi_create_promise(napi_env env,napi_deferred * deferred,napi_value * promise)2873 NAPI_EXTERN napi_status napi_create_promise(napi_env env, napi_deferred* deferred, napi_value* promise)
2874 {
2875     NAPI_PREAMBLE(env);
2876     auto engine = reinterpret_cast<NativeEngine*>(env);
2877     if (panda::JSNApi::HasPendingException(engine->GetEcmaVm())) {
2878         return napi_pending_exception;
2879     }
2880     CHECK_ARG(env, deferred);
2881     CHECK_ARG(env, promise);
2882 
2883     auto resultValue = engine->CreatePromise(reinterpret_cast<NativeDeferred**>(deferred));
2884     *promise = resultValue;
2885 
2886     return GET_RETURN_STATUS(env);
2887 }
2888 
napi_resolve_deferred(napi_env env,napi_deferred deferred,napi_value resolution)2889 NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution)
2890 {
2891     NAPI_PREAMBLE(env);
2892     CHECK_ARG(env, deferred);
2893     CHECK_ARG(env, resolution);
2894 
2895     auto nativeDeferred = reinterpret_cast<NativeDeferred*>(deferred);
2896     nativeDeferred->Resolve(resolution);
2897     delete nativeDeferred;
2898     return GET_RETURN_STATUS(env);
2899 }
2900 
napi_reject_deferred(napi_env env,napi_deferred deferred,napi_value rejection)2901 NAPI_EXTERN napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection)
2902 {
2903     NAPI_PREAMBLE(env);
2904     CHECK_ARG(env, deferred);
2905     CHECK_ARG(env, rejection);
2906 
2907     auto nativeDeferred = reinterpret_cast<NativeDeferred*>(deferred);
2908     nativeDeferred->Reject(rejection);
2909     delete nativeDeferred;
2910     return GET_RETURN_STATUS(env);
2911 }
2912 
napi_is_promise(napi_env env,napi_value value,bool * is_promise)2913 NAPI_EXTERN napi_status napi_is_promise(napi_env env, napi_value value, bool* is_promise)
2914 {
2915     CHECK_ENV(env);
2916     CHECK_ARG(env, value);
2917     CHECK_ARG(env, is_promise);
2918 
2919     auto nativeValue = LocalValueFromJsValue(value);
2920     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2921     panda::JsiFastNativeScope fastNativeScope(vm);
2922     *is_promise = nativeValue->IsPromise(vm);
2923 
2924     return napi_clear_last_error(env);
2925 }
2926 
2927 // promise reject events
napi_set_promise_rejection_callback(napi_env env,napi_ref ref,napi_ref checkRef)2928 NAPI_EXTERN napi_status napi_set_promise_rejection_callback(napi_env env, napi_ref ref, napi_ref checkRef)
2929 {
2930     CHECK_ENV(env);
2931     CHECK_ARG(env, ref);
2932     CHECK_ARG(env, checkRef);
2933 
2934     auto rejectCallbackRef = reinterpret_cast<NativeReference*>(ref);
2935     auto checkCallbackRef = reinterpret_cast<NativeReference*>(checkRef);
2936     if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
2937         HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
2938     } else {
2939         auto engine = reinterpret_cast<NativeEngine*>(env);
2940         auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
2941         engine->SetPromiseRejectCallBackRef(rejectCallbackRef);
2942         engine->SetCheckCallbackRef(checkCallbackRef);
2943         panda::JSNApi::SetHostPromiseRejectionTracker(const_cast<EcmaVM*>(vm), engine->GetPromiseRejectCallback(),
2944                                                       reinterpret_cast<void*>(engine));
2945     }
2946 
2947     return napi_clear_last_error(env);
2948 }
2949 
2950 // Running a script
napi_run_script(napi_env env,napi_value script,napi_value * result)2951 NAPI_EXTERN napi_status napi_run_script(napi_env env, napi_value script, napi_value* result)
2952 {
2953     CHECK_ENV(env);
2954     CHECK_ARG(env, script);
2955     CHECK_ARG(env, result);
2956 
2957     *result = nullptr;
2958     return napi_clear_last_error(env);
2959 }
2960 
napi_run_actor(napi_env env,uint8_t * buffer,size_t bufferSize,const char * descriptor,napi_value * result,char * entryPoint)2961 NAPI_EXTERN napi_status napi_run_actor(napi_env env,
2962                                        uint8_t* buffer,
2963                                        size_t bufferSize,
2964                                        const char* descriptor,
2965                                        napi_value* result,
2966                                        char* entryPoint)
2967 {
2968     NAPI_PREAMBLE(env);
2969     CHECK_ARG(env, result);
2970 
2971     auto engine = reinterpret_cast<NativeEngine*>(env);
2972     *result = engine->RunActor(buffer, bufferSize, descriptor, entryPoint, false);
2973     return GET_RETURN_STATUS(env);
2974 }
2975 
napi_load_module(napi_env env,const char * path,napi_value * result)2976 NAPI_EXTERN napi_status napi_load_module(napi_env env, const char* path, napi_value* result)
2977 {
2978     NAPI_PREAMBLE(env);
2979     CHECK_ARG(env, result);
2980     auto engine = reinterpret_cast<NativeEngine*>(env);
2981     *result = engine->NapiLoadModule(path, nullptr);
2982     return GET_RETURN_STATUS(env);
2983 }
2984 
napi_load_module_with_info(napi_env env,const char * path,const char * module_info,napi_value * result)2985 NAPI_EXTERN napi_status napi_load_module_with_info(napi_env env,
2986                                                    const char* path,
2987                                                    const char* module_info,
2988                                                    napi_value* result)
2989 {
2990     NAPI_PREAMBLE(env);
2991     CHECK_ARG(env, result);
2992     auto engine = reinterpret_cast<NativeEngine*>(env);
2993     *result = engine->NapiLoadModuleWithInfo(path, module_info);
2994     return GET_RETURN_STATUS(env);
2995 }
2996 // Memory management
napi_adjust_external_memory(napi_env env,int64_t change_in_bytes,int64_t * adjusted_value)2997 NAPI_INNER_EXTERN napi_status napi_adjust_external_memory(
2998     napi_env env, int64_t change_in_bytes, int64_t* adjusted_value)
2999 {
3000     CHECK_ENV(env);
3001     CHECK_ARG(env, adjusted_value);
3002 
3003     auto engine = reinterpret_cast<NativeEngine*>(env);
3004     engine->AdjustExternalMemory(change_in_bytes, adjusted_value);
3005 
3006     return napi_clear_last_error(env);
3007 }
3008 
napi_is_callable(napi_env env,napi_value value,bool * result)3009 NAPI_EXTERN napi_status napi_is_callable(napi_env env, napi_value value, bool* result)
3010 {
3011     CHECK_ENV(env);
3012     CHECK_ARG(env, value);
3013     CHECK_ARG(env, result);
3014 
3015     auto nativeValue = LocalValueFromJsValue(value);
3016     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3017     panda::JsiFastNativeScope fastNativeScope(vm);
3018 
3019     *result = nativeValue->IsFunction(vm);
3020 
3021     return napi_clear_last_error(env);
3022 }
3023 
napi_is_arguments_object(napi_env env,napi_value value,bool * result)3024 NAPI_EXTERN napi_status napi_is_arguments_object(napi_env env, napi_value value, bool* result)
3025 {
3026     CHECK_ENV(env);
3027     CHECK_ARG(env, value);
3028     CHECK_ARG(env, result);
3029 
3030     auto nativeValue = LocalValueFromJsValue(value);
3031     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3032     panda::JsiFastNativeScope fastNativeScope(vm);
3033 
3034     *result = nativeValue->IsArgumentsObject(vm);
3035 
3036     return napi_clear_last_error(env);
3037 }
3038 
napi_is_async_function(napi_env env,napi_value value,bool * result)3039 NAPI_EXTERN napi_status napi_is_async_function(napi_env env, napi_value value, bool* result)
3040 {
3041     CHECK_ENV(env);
3042     CHECK_ARG(env, value);
3043     CHECK_ARG(env, result);
3044 
3045     auto nativeValue = LocalValueFromJsValue(value);
3046     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3047     panda::JsiFastNativeScope fastNativeScope(vm);
3048 
3049     *result = nativeValue->IsAsyncFunction(vm);
3050     return napi_clear_last_error(env);
3051 }
3052 
napi_is_boolean_object(napi_env env,napi_value value,bool * result)3053 NAPI_EXTERN napi_status napi_is_boolean_object(napi_env env, napi_value value, bool* result)
3054 {
3055     CHECK_ENV(env);
3056     CHECK_ARG(env, value);
3057     CHECK_ARG(env, result);
3058 
3059     auto nativeValue = LocalValueFromJsValue(value);
3060     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3061     panda::JsiFastNativeScope fastNativeScope(vm);
3062 
3063     *result = nativeValue->IsJSPrimitiveBoolean(vm);
3064 
3065     return napi_clear_last_error(env);
3066 }
3067 
napi_is_generator_function(napi_env env,napi_value value,bool * result)3068 NAPI_EXTERN napi_status napi_is_generator_function(napi_env env, napi_value value, bool* result)
3069 {
3070     CHECK_ENV(env);
3071     CHECK_ARG(env, value);
3072     CHECK_ARG(env, result);
3073 
3074     auto nativeValue = LocalValueFromJsValue(value);
3075     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3076     panda::JsiFastNativeScope fastNativeScope(vm);
3077 
3078     *result = nativeValue->IsGeneratorFunction(vm);
3079 
3080     return napi_clear_last_error(env);
3081 }
3082 
napi_is_map_iterator(napi_env env,napi_value value,bool * result)3083 NAPI_EXTERN napi_status napi_is_map_iterator(napi_env env, napi_value value, bool* result)
3084 {
3085     CHECK_ENV(env);
3086     CHECK_ARG(env, value);
3087     CHECK_ARG(env, result);
3088 
3089     auto nativeValue = LocalValueFromJsValue(value);
3090     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3091     panda::JsiFastNativeScope fastNativeScope(vm);
3092 
3093     *result = nativeValue->IsMapIterator(vm);
3094 
3095     return napi_clear_last_error(env);
3096 }
3097 
napi_is_set_iterator(napi_env env,napi_value value,bool * result)3098 NAPI_EXTERN napi_status napi_is_set_iterator(napi_env env, napi_value value, bool* result)
3099 {
3100     CHECK_ENV(env);
3101     CHECK_ARG(env, value);
3102     CHECK_ARG(env, result);
3103 
3104     auto nativeValue = LocalValueFromJsValue(value);
3105     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3106     panda::JsiFastNativeScope fastNativeScope(vm);
3107 
3108     *result = nativeValue->IsSetIterator(vm);
3109 
3110     return napi_clear_last_error(env);
3111 }
3112 
napi_is_generator_object(napi_env env,napi_value value,bool * result)3113 NAPI_EXTERN napi_status napi_is_generator_object(napi_env env, napi_value value, bool* result)
3114 {
3115     CHECK_ENV(env);
3116     CHECK_ARG(env, value);
3117     CHECK_ARG(env, result);
3118 
3119     auto nativeValue = LocalValueFromJsValue(value);
3120     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3121     panda::JsiFastNativeScope fastNativeScope(vm);
3122 
3123     *result = nativeValue->IsGeneratorObject(vm);
3124 
3125     return napi_clear_last_error(env);
3126 }
3127 
napi_is_module_namespace_object(napi_env env,napi_value value,bool * result)3128 NAPI_EXTERN napi_status napi_is_module_namespace_object(napi_env env, napi_value value, bool* result)
3129 {
3130     CHECK_ENV(env);
3131     CHECK_ARG(env, value);
3132     CHECK_ARG(env, result);
3133 
3134     auto nativeValue = LocalValueFromJsValue(value);
3135     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3136     panda::JsiFastNativeScope fastNativeScope(vm);
3137 
3138     *result = nativeValue->IsModuleNamespaceObject(vm);
3139 
3140     return napi_clear_last_error(env);
3141 }
3142 
napi_is_proxy(napi_env env,napi_value value,bool * result)3143 NAPI_EXTERN napi_status napi_is_proxy(napi_env env, napi_value value, bool* result)
3144 {
3145     CHECK_ENV(env);
3146     CHECK_ARG(env, value);
3147     CHECK_ARG(env, result);
3148 
3149     auto nativeValue = LocalValueFromJsValue(value);
3150     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3151     panda::JsiFastNativeScope fastNativeScope(vm);
3152 
3153     *result = nativeValue->IsProxy(vm);
3154     return napi_clear_last_error(env);
3155 }
3156 
napi_is_reg_exp(napi_env env,napi_value value,bool * result)3157 NAPI_EXTERN napi_status napi_is_reg_exp(napi_env env, napi_value value, bool* result)
3158 {
3159     CHECK_ENV(env);
3160     CHECK_ARG(env, value);
3161     CHECK_ARG(env, result);
3162 
3163     auto nativeValue = LocalValueFromJsValue(value);
3164     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3165     panda::JsiFastNativeScope fastNativeScope(vm);
3166 
3167     *result = nativeValue->IsRegExp(vm);
3168     return napi_clear_last_error(env);
3169 }
3170 
napi_is_number_object(napi_env env,napi_value value,bool * result)3171 NAPI_EXTERN napi_status napi_is_number_object(napi_env env, napi_value value, bool* result)
3172 {
3173     CHECK_ENV(env);
3174     CHECK_ARG(env, value);
3175     CHECK_ARG(env, result);
3176 
3177     auto nativeValue = LocalValueFromJsValue(value);
3178     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3179     panda::JsiFastNativeScope fastNativeScope(vm);
3180 
3181     *result = nativeValue->IsJSPrimitiveNumber(vm);
3182 
3183     return napi_clear_last_error(env);
3184 }
3185 
napi_is_map(napi_env env,napi_value value,bool * result)3186 NAPI_EXTERN napi_status napi_is_map(napi_env env, napi_value value, bool* result)
3187 {
3188     CHECK_ENV(env);
3189     CHECK_ARG(env, value);
3190     CHECK_ARG(env, result);
3191 
3192     auto nativeValue = LocalValueFromJsValue(value);
3193     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3194     panda::JsiFastNativeScope fastNativeScope(vm);
3195 
3196     *result = nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm);
3197     return napi_clear_last_error(env);
3198 }
3199 
napi_is_set(napi_env env,napi_value value,bool * result)3200 NAPI_EXTERN napi_status napi_is_set(napi_env env, napi_value value, bool* result)
3201 {
3202     CHECK_ENV(env);
3203     CHECK_ARG(env, value);
3204     CHECK_ARG(env, result);
3205 
3206     auto nativeValue = LocalValueFromJsValue(value);
3207     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3208     panda::JsiFastNativeScope fastNativeScope(vm);
3209 
3210     *result = nativeValue->IsSet(vm) || nativeValue->IsSharedSet(vm);
3211     return napi_clear_last_error(env);
3212 }
3213 
napi_is_string_object(napi_env env,napi_value value,bool * result)3214 NAPI_EXTERN napi_status napi_is_string_object(napi_env env, napi_value value, bool* result)
3215 {
3216     CHECK_ENV(env);
3217     CHECK_ARG(env, value);
3218     CHECK_ARG(env, result);
3219 
3220     auto nativeValue = LocalValueFromJsValue(value);
3221     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3222     panda::JsiFastNativeScope fastNativeScope(vm);
3223 
3224     *result = nativeValue->IsJSPrimitiveString(vm);
3225 
3226     return napi_clear_last_error(env);
3227 }
3228 
napi_is_symbol_object(napi_env env,napi_value value,bool * result)3229 NAPI_EXTERN napi_status napi_is_symbol_object(napi_env env, napi_value value, bool* result)
3230 {
3231     CHECK_ENV(env);
3232     CHECK_ARG(env, value);
3233     CHECK_ARG(env, result);
3234 
3235     auto nativeValue = LocalValueFromJsValue(value);
3236     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3237     panda::JsiFastNativeScope fastNativeScope(vm);
3238 
3239     *result = nativeValue->IsJSPrimitiveSymbol(vm);
3240     return napi_clear_last_error(env);
3241 }
3242 
napi_is_weak_map(napi_env env,napi_value value,bool * result)3243 NAPI_EXTERN napi_status napi_is_weak_map(napi_env env, napi_value value, bool* result)
3244 {
3245     CHECK_ENV(env);
3246     CHECK_ARG(env, value);
3247     CHECK_ARG(env, result);
3248 
3249     auto nativeValue = LocalValueFromJsValue(value);
3250     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3251     panda::JsiFastNativeScope fastNativeScope(vm);
3252 
3253     *result = nativeValue->IsWeakMap(vm);
3254     return napi_clear_last_error(env);
3255 }
3256 
napi_is_weak_set(napi_env env,napi_value value,bool * result)3257 NAPI_EXTERN napi_status napi_is_weak_set(napi_env env, napi_value value, bool* result)
3258 {
3259     CHECK_ENV(env);
3260     CHECK_ARG(env, value);
3261     CHECK_ARG(env, result);
3262 
3263     auto nativeValue = LocalValueFromJsValue(value);
3264     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3265     panda::JsiFastNativeScope fastNativeScope(vm);
3266 
3267     *result = nativeValue->IsWeakSet(vm);
3268     return napi_clear_last_error(env);
3269 }
3270 
napi_create_runtime(napi_env env,napi_env * result_env)3271 NAPI_EXTERN napi_status napi_create_runtime(napi_env env, napi_env* result_env)
3272 {
3273     CHECK_ENV(env);
3274     CHECK_ARG(env, result_env);
3275 
3276     auto engine = reinterpret_cast<NativeEngine*>(env);
3277     auto result = engine->CreateRuntime();
3278     *result_env = reinterpret_cast<napi_env>(result);
3279 
3280     return napi_clear_last_error(env);
3281 }
3282 
napi_serialize(napi_env env,napi_value object,napi_value transfer_list,napi_value clone_list,void ** result)3283 NAPI_EXTERN napi_status napi_serialize(napi_env env,
3284                                        napi_value object,
3285                                        napi_value transfer_list,
3286                                        napi_value clone_list,
3287                                        void** result)
3288 {
3289     CHECK_ENV(env);
3290     CHECK_ARG(env, object);
3291     CHECK_ARG(env, transfer_list);
3292     CHECK_ARG(env, clone_list);
3293     CHECK_ARG(env, result);
3294 
3295     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3296     auto nativeValue = LocalValueFromJsValue(object);
3297     auto transferList = LocalValueFromJsValue(transfer_list);
3298     RETURN_STATUS_IF_FALSE(env, transferList->IsUndefined() || transferList->IsJSArray(vm), napi_invalid_arg);
3299     auto cloneList = LocalValueFromJsValue(clone_list);
3300     RETURN_STATUS_IF_FALSE(env, cloneList->IsUndefined() || cloneList->IsJSArray(vm), napi_invalid_arg);
3301     *result = panda::JSNApi::SerializeValue(vm, nativeValue, transferList, cloneList, false, false);
3302 
3303     return napi_clear_last_error(env);
3304 }
3305 
napi_serialize_inner(napi_env env,napi_value object,napi_value transfer_list,napi_value clone_list,bool defaultTransfer,bool defaultCloneSendable,void ** result)3306 NAPI_EXTERN napi_status napi_serialize_inner(napi_env env, napi_value object, napi_value transfer_list,
3307                                              napi_value clone_list, bool defaultTransfer, bool defaultCloneSendable,
3308                                              void** result)
3309 {
3310     CHECK_ENV(env);
3311     CHECK_ARG(env, object);
3312     CHECK_ARG(env, transfer_list);
3313     CHECK_ARG(env, result);
3314 
3315     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3316     auto nativeValue = LocalValueFromJsValue(object);
3317     auto transferList = LocalValueFromJsValue(transfer_list);
3318     auto cloneList = LocalValueFromJsValue(clone_list);
3319     *result =
3320         panda::JSNApi::SerializeValue(vm, nativeValue, transferList, cloneList, defaultTransfer, defaultCloneSendable);
3321 
3322     return napi_clear_last_error(env);
3323 }
3324 
napi_deserialize(napi_env env,void * buffer,napi_value * object)3325 NAPI_EXTERN napi_status napi_deserialize(napi_env env, void* buffer, napi_value* object)
3326 {
3327     CHECK_ENV(env);
3328     CHECK_ARG(env, buffer);
3329     CHECK_ARG(env, object);
3330 
3331     auto engine = reinterpret_cast<NativeEngine*>(env);
3332     auto vm = engine->GetEcmaVm();
3333     Local<panda::JSValueRef> res = panda::JSNApi::DeserializeValue(vm, buffer, reinterpret_cast<void*>(engine));
3334     *object = JsValueFromLocalValue(res);
3335 
3336     return napi_clear_last_error(env);
3337 }
3338 
napi_delete_serialization_data(napi_env env,void * buffer)3339 NAPI_EXTERN napi_status napi_delete_serialization_data(napi_env env, void* buffer)
3340 {
3341     CHECK_ENV(env);
3342     CHECK_ARG(env, buffer);
3343 
3344     panda::JSNApi::DeleteSerializationData(buffer);
3345 
3346     return napi_clear_last_error(env);
3347 }
3348 
napi_create_bigint_int64(napi_env env,int64_t value,napi_value * result)3349 NAPI_EXTERN napi_status napi_create_bigint_int64(napi_env env, int64_t value, napi_value* result)
3350 {
3351     CHECK_ENV(env);
3352     CHECK_ARG(env, result);
3353 
3354     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3355     Local<panda::BigIntRef> object = panda::BigIntRef::New(vm, value);
3356     *result = JsValueFromLocalValue(object);
3357 
3358     return napi_clear_last_error(env);
3359 }
3360 
napi_create_bigint_uint64(napi_env env,uint64_t value,napi_value * result)3361 NAPI_EXTERN napi_status napi_create_bigint_uint64(napi_env env, uint64_t value, napi_value* result)
3362 {
3363     CHECK_ENV(env);
3364     CHECK_ARG(env, result);
3365 
3366     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3367     Local<panda::BigIntRef> object = panda::BigIntRef::New(vm, value);
3368     *result = JsValueFromLocalValue(object);
3369 
3370     return napi_clear_last_error(env);
3371 }
3372 
napi_get_value_bigint_int64(napi_env env,napi_value value,int64_t * result,bool * lossless)3373 NAPI_EXTERN napi_status napi_get_value_bigint_int64(
3374     napi_env env, napi_value value, int64_t* result, bool* lossless)
3375 {
3376     CHECK_ENV(env);
3377     CHECK_ARG(env, value);
3378     CHECK_ARG(env, result);
3379     CHECK_ARG(env, lossless);
3380 
3381     auto nativeValue = LocalValueFromJsValue(value);
3382     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3383     panda::JsiFastNativeScope fastNativeScope(vm);
3384     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(vm), napi_bigint_expected);
3385     Local<panda::BigIntRef> bigIntVal = nativeValue->ToBigInt(vm);
3386     bigIntVal->BigIntToInt64(vm, result, lossless);
3387 
3388     return napi_clear_last_error(env);
3389 }
3390 
napi_get_value_bigint_uint64(napi_env env,napi_value value,uint64_t * result,bool * lossless)3391 NAPI_EXTERN napi_status napi_get_value_bigint_uint64(
3392     napi_env env, napi_value value, uint64_t* result, bool* lossless)
3393 {
3394     CHECK_ENV(env);
3395     CHECK_ARG(env, value);
3396     CHECK_ARG(env, result);
3397     CHECK_ARG(env, lossless);
3398 
3399     auto nativeValue = LocalValueFromJsValue(value);
3400     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3401     panda::JsiFastNativeScope fastNativeScope(vm);
3402     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(vm), napi_bigint_expected);
3403     Local<panda::BigIntRef> bigIntVal = nativeValue->ToBigInt(vm);
3404     bigIntVal->BigIntToUint64(vm, result, lossless);
3405 
3406     return napi_clear_last_error(env);
3407 }
3408 
napi_is_date(napi_env env,napi_value value,bool * result)3409 NAPI_EXTERN napi_status napi_is_date(napi_env env, napi_value value, bool* result)
3410 {
3411     CHECK_ENV(env);
3412     CHECK_ARG(env, value);
3413     CHECK_ARG(env, result);
3414 
3415     auto nativeValue = LocalValueFromJsValue(value);
3416     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3417     panda::JsiFastNativeScope fastNativeScope(vm);
3418 
3419     *result = nativeValue->IsDate(vm);
3420     return napi_clear_last_error(env);
3421 }
3422 
napi_is_detached_arraybuffer(napi_env env,napi_value arraybuffer,bool * result)3423 NAPI_EXTERN napi_status napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer, bool* result)
3424 {
3425     CHECK_ENV(env);
3426     CHECK_ARG(env, arraybuffer);
3427     CHECK_ARG(env, result);
3428 
3429     auto nativeValue = LocalValueFromJsValue(arraybuffer);
3430     bool isArrayBuffer = false;
3431     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3432     panda::JsiFastNativeScope fastNativeScope(vm);
3433 
3434     bool isDetach = nativeValue->IsDetachedArraybuffer(vm, isArrayBuffer);
3435     if (isArrayBuffer) {
3436         *result = isDetach;
3437         return napi_clear_last_error(env);
3438     } else {
3439         return napi_set_last_error(env, napi_invalid_arg);
3440     }
3441 }
3442 
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)3443 NAPI_EXTERN napi_status napi_get_all_property_names(
3444     napi_env env, napi_value object, napi_key_collection_mode key_mode,
3445     napi_key_filter key_filter, napi_key_conversion key_conversion, napi_value* result)
3446 {
3447     NAPI_PREAMBLE(env);
3448     CHECK_ARG(env, object);
3449     CHECK_ARG(env, result);
3450     auto nativeValue = LocalValueFromJsValue(object);
3451     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3452     panda::JsiFastNativeScope fastNativeScope(vm);
3453     CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
3454     uint32_t filter = NATIVE_DEFAULT;
3455     if (key_filter & napi_key_writable) {
3456         filter = static_cast<uint32_t>(filter | NATIVE_WRITABLE);
3457     }
3458     if (key_filter & napi_key_enumerable) {
3459         filter = static_cast<uint32_t>(filter | NATIVE_ENUMERABLE);
3460     }
3461     if (key_filter & napi_key_configurable) {
3462         filter = static_cast<uint32_t>(filter | NATIVE_CONFIGURABLE);
3463     }
3464     if (key_filter & napi_key_skip_strings) {
3465         filter = static_cast<uint32_t>(filter | NATIVE_KEY_SKIP_STRINGS);
3466     }
3467     if (key_filter & napi_key_skip_symbols) {
3468         filter = static_cast<uint32_t>(filter | NATIVE_KEY_SKIP_SYMBOLS);
3469     }
3470 
3471     switch (key_mode) {
3472         case napi_key_include_prototypes:
3473             filter = static_cast<uint32_t>(filter | NATIVE_KEY_INCLUDE_PROTOTYPES);
3474             break;
3475         case napi_key_own_only:
3476             filter = static_cast<uint32_t>(filter | NATIVE_KEY_OWN_ONLY);
3477             break;
3478         default:
3479             *result = nullptr;
3480             HILOG_ERROR("%{public}s invalid arg", __func__);
3481             return napi_set_last_error(env, napi_invalid_arg);
3482     }
3483 
3484     switch (key_conversion) {
3485         case napi_key_keep_numbers:
3486             filter = static_cast<uint32_t>(filter | NATIVE_KEY_KEEP_NUMBERS);
3487             break;
3488         case napi_key_numbers_to_strings:
3489             filter = static_cast<uint32_t>(filter | NATIVE_KEY_NUMBERS_TO_STRINGS);
3490             break;
3491         default:
3492             *result = nullptr;
3493             HILOG_ERROR("%{public}s invalid arg", __func__);
3494             return napi_set_last_error(env, napi_invalid_arg);
3495     }
3496     Local<panda::ArrayRef> arrayVal = obj->GetAllPropertyNames(vm, filter);
3497     *result = JsValueFromLocalValue(arrayVal);
3498     return GET_RETURN_STATUS(env);
3499 }
3500 
napi_detach_arraybuffer(napi_env env,napi_value arraybuffer)3501 NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer)
3502 {
3503     CHECK_ENV(env);
3504     CHECK_ARG(env, arraybuffer);
3505 
3506     auto nativeValue = LocalValueFromJsValue(arraybuffer);
3507     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3508     panda::JsiFastNativeScope fastNativeScope(vm);
3509 
3510     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3511     bool isArrayBuffer = false;
3512     nativeValue->DetachedArraybuffer(vm, isArrayBuffer);
3513     if (!isArrayBuffer) {
3514         return napi_set_last_error(env, napi_invalid_arg);
3515     }
3516     return napi_clear_last_error(env);
3517 }
3518 
napi_type_tag_object(napi_env env,napi_value js_object,const napi_type_tag * type_tag)3519 NAPI_EXTERN napi_status napi_type_tag_object(napi_env env, napi_value js_object, const napi_type_tag* type_tag)
3520 {
3521     NAPI_PREAMBLE(env);
3522     CHECK_ARG(env, js_object);
3523     CHECK_ARG(env, type_tag);
3524 
3525     auto nativeValue = LocalValueFromJsValue(js_object);
3526     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3527     panda::JsiFastNativeScope fastNativeScope(vm);
3528     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3529     auto obj = nativeValue->ToEcmaObject(vm);
3530     NapiTypeTag* typeTag = (NapiTypeTag*)type_tag;
3531     const char name[] = "ACENAPI_TYPETAG";
3532     bool hasPribate = false;
3533     bool result = true;
3534     Local<panda::StringRef> key = StringRef::NewFromUtf8(vm, name);
3535     hasPribate = obj->Has(vm, key);
3536     if (!hasPribate) {
3537         constexpr int bigintMod = 2; // 2 : used for even number judgment
3538         int sign_bit = 0;
3539         size_t word_count = 2;
3540         bool sign = false;
3541         if ((sign_bit % bigintMod) == 1) {
3542             sign = true;
3543         }
3544         uint32_t size = (uint32_t)word_count;
3545         Local<panda::JSValueRef> value = panda::BigIntRef::CreateBigWords(vm, sign, size,
3546                                                                           reinterpret_cast<const uint64_t*>(typeTag));
3547         Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
3548         result = obj->Set(vm, key, value);
3549     }
3550     if (!result) {
3551         HILOG_ERROR("%{public}s invalid arg", __func__);
3552         return napi_set_last_error(env, napi_invalid_arg);
3553     }
3554 
3555     return napi_clear_last_error(env);
3556 }
3557 
BigIntGetWordsArray(const EcmaVM * vm,Local<panda::BigIntRef> & value,int * signBit,size_t * wordCount,uint64_t * words)3558 bool BigIntGetWordsArray(const EcmaVM* vm, Local<panda::BigIntRef> &value, int* signBit,
3559                          size_t* wordCount, uint64_t* words)
3560 {
3561     if (wordCount == nullptr) {
3562         return false;
3563     }
3564     size_t size = static_cast<size_t>(value->GetWordsArraySize(vm));
3565     if (signBit == nullptr && words == nullptr) {
3566         *wordCount = size;
3567         return true;
3568     } else if (signBit != nullptr && words != nullptr) {
3569         if (size > *wordCount) {
3570             size = *wordCount;
3571         }
3572         bool sign = false;
3573         value->GetWordsArray(vm, &sign, size, words);
3574         if (sign) {
3575             *signBit = 1;
3576         } else {
3577             *signBit = 0;
3578         }
3579         *wordCount = size;
3580         return true;
3581     }
3582     return false;
3583 }
3584 
napi_check_object_type_tag(napi_env env,napi_value js_object,const napi_type_tag * type_tag,bool * result)3585 NAPI_EXTERN napi_status napi_check_object_type_tag(napi_env env,
3586                                                    napi_value js_object,
3587                                                    const napi_type_tag* type_tag,
3588                                                    bool* result)
3589 {
3590     NAPI_PREAMBLE(env);
3591     CHECK_ARG(env, js_object);
3592     CHECK_ARG(env, type_tag);
3593     CHECK_ARG(env, result);
3594 
3595     auto nativeValue = LocalValueFromJsValue(js_object);
3596     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3597     panda::JsiFastNativeScope fastNativeScope(vm);
3598     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3599     auto obj = nativeValue->ToEcmaObject(vm);
3600     NapiTypeTag* typeTag = (NapiTypeTag*)type_tag;
3601     *result = false;
3602     const char name[] = "ACENAPI_TYPETAG";
3603 
3604     Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
3605     *result = obj->Has(vm, key);
3606     if (*result) {
3607         Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
3608         Local<panda::JSValueRef> object = obj->Get(vm, key);
3609         if (object->IsBigInt(vm)) {
3610             int sign;
3611             size_t size = 2; // 2: Indicates that the number of elements is 2
3612             NapiTypeTag tag;
3613             Local<panda::BigIntRef> bigintObj = object->ToBigInt(vm);
3614             BigIntGetWordsArray(vm, bigintObj, &sign, &size, reinterpret_cast<uint64_t*>(&tag));
3615             if (sign == 0 && ((size == 1) || (size == 2))) { // 2: Indicates that the number of elements is 2
3616                 *result = (tag.lower == typeTag->lower && tag.upper == typeTag->upper);
3617             }
3618         }
3619     }
3620     return napi_clear_last_error(env);
3621 }
3622 
napi_create_date(napi_env env,double time,napi_value * result)3623 NAPI_EXTERN napi_status napi_create_date(napi_env env, double time, napi_value* result)
3624 {
3625     NAPI_PREAMBLE(env);
3626     CHECK_ARG(env, result);
3627 
3628     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3629     *result = JsValueFromLocalValue(DateRef::New(vm, time));
3630 
3631     return napi_clear_last_error(env);
3632 }
3633 
napi_get_date_value(napi_env env,napi_value value,double * result)3634 NAPI_EXTERN napi_status napi_get_date_value(napi_env env, napi_value value, double* result)
3635 {
3636     NAPI_PREAMBLE(env);
3637     CHECK_ARG(env, value);
3638     CHECK_ARG(env, result);
3639 
3640     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3641     auto nativeValue = LocalValueFromJsValue(value);
3642     panda::JsiFastNativeScope fastNativeScope(vm);
3643 
3644     auto IsDate_result = nativeValue->IsDate(vm);
3645     Local<panda::DateRef> dateObj(nativeValue);
3646     if (IsDate_result) {
3647         *result = dateObj->GetTime(vm);
3648     } else {
3649         HILOG_ERROR("%{public}s date expected", __func__);
3650         return napi_set_last_error(env, napi_date_expected);
3651     }
3652 
3653     return napi_clear_last_error(env);
3654 }
3655 
napi_add_finalizer(napi_env env,napi_value js_object,void * native_object,napi_finalize finalize_cb,void * finalize_hint,napi_ref * result)3656 NAPI_EXTERN napi_status napi_add_finalizer(napi_env env,
3657                                            napi_value js_object,
3658                                            void* native_object,
3659                                            napi_finalize finalize_cb,
3660                                            void* finalize_hint,
3661                                            napi_ref* result)
3662 {
3663     CHECK_ENV(env);
3664     CHECK_ARG(env, js_object);
3665     CHECK_ARG(env, finalize_cb);
3666 
3667     auto nativeValue = LocalValueFromJsValue(js_object);
3668     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
3669     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3670     panda::JsiFastNativeScope fastNativeScope(vm);
3671 
3672     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3673     NativeReference* reference = nullptr;
3674     auto engine = reinterpret_cast<NativeEngine*>(env);
3675     if (result != nullptr) {
3676         reference = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
3677         *result = reinterpret_cast<napi_ref>(reference);
3678     } else {
3679         reference = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
3680     }
3681     return napi_clear_last_error(env);
3682 }
3683 
napi_create_bigint_words(napi_env env,int sign_bit,size_t word_count,const uint64_t * words,napi_value * result)3684 NAPI_EXTERN napi_status napi_create_bigint_words(napi_env env,
3685                                                  int sign_bit,
3686                                                  size_t word_count,
3687                                                  const uint64_t* words,
3688                                                  napi_value* result)
3689 {
3690     NAPI_PREAMBLE(env);
3691     CHECK_ARG(env, words);
3692     CHECK_ARG(env, result);
3693     RETURN_STATUS_IF_FALSE(env, word_count <= INT_MAX, napi_invalid_arg);
3694 
3695     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3696     constexpr int bigintMod = 2; // 2 : used for even number judgment
3697     bool sign = false;
3698     if ((sign_bit % bigintMod) == 1) {
3699         sign = true;
3700     }
3701     uint32_t size = (uint32_t)word_count;
3702     Local<panda::JSValueRef> value = panda::BigIntRef::CreateBigWords(vm, sign, size, words);
3703 
3704     if (panda::JSNApi::HasPendingException(vm)) {
3705         HILOG_ERROR("%{public}s pending exception", __func__);
3706         return napi_set_last_error(env, napi_pending_exception);
3707     }
3708     *result = JsValueFromLocalValue(value);
3709     return GET_RETURN_STATUS(env);
3710 }
3711 
napi_get_value_bigint_words(napi_env env,napi_value value,int * sign_bit,size_t * word_count,uint64_t * words)3712 NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env,
3713                                                     napi_value value,
3714                                                     int* sign_bit,
3715                                                     size_t* word_count,
3716                                                     uint64_t* words)
3717 {
3718     CHECK_ENV(env);
3719     CHECK_ARG(env, value);
3720     CHECK_ARG(env, word_count);
3721 
3722     auto nativeValue = LocalValueFromJsValue(value);
3723     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3724     panda::JsiFastNativeScope fastNativeScope(vm);
3725 
3726     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(vm), napi_object_expected);
3727     auto BigintObj = nativeValue->ToBigInt(vm);
3728     if (word_count == nullptr) {
3729         return napi_set_last_error(env, napi_invalid_arg);
3730     }
3731     size_t size = static_cast<size_t>(BigintObj->GetWordsArraySize(vm));
3732     if (sign_bit == nullptr && words == nullptr) {
3733         *word_count = size;
3734         return napi_set_last_error(env, napi_ok);
3735     } else if (sign_bit != nullptr && words != nullptr) {
3736         if (size > *word_count) {
3737             size = *word_count;
3738         }
3739         bool sign = false;
3740         BigintObj->GetWordsArray(vm, &sign, size, words);
3741         if (sign) {
3742             *sign_bit = 1;
3743         } else {
3744             *sign_bit = 0;
3745         }
3746         *word_count = size;
3747         return napi_set_last_error(env, napi_ok);
3748     }
3749 
3750     return napi_clear_last_error(env);
3751 }
3752 
napi_run_script_path(napi_env env,const char * path,napi_value * result)3753 NAPI_EXTERN napi_status napi_run_script_path(napi_env env, const char* path, napi_value* result)
3754 {
3755     NAPI_PREAMBLE(env);
3756     CHECK_ARG(env, result);
3757 
3758     auto engine = reinterpret_cast<NativeEngine*>(env);
3759     std::string pathStr(path);
3760     if (engine->IsApplicationApiVersionAPI11Plus()) {
3761         pathStr = panda::JSNApi::NormalizePath(path);
3762     }
3763     HILOG_DEBUG("napi_run_script_path path: %{public}s", pathStr.c_str());
3764     if (engine->IsRestrictedWorkerThread()) {
3765         *result = engine->RunScriptInRestrictedThread(pathStr.c_str());
3766     } else {
3767         *result = engine->RunScript(pathStr.c_str());
3768     }
3769     return GET_RETURN_STATUS(env);
3770 }
3771 
napi_is_big_int64_array(napi_env env,napi_value value,bool * result)3772 NAPI_EXTERN napi_status napi_is_big_int64_array(napi_env env, napi_value value, bool* result)
3773 {
3774     CHECK_ENV(env);
3775     CHECK_ARG(env, value);
3776     CHECK_ARG(env, result);
3777 
3778     auto nativeValue = LocalValueFromJsValue(value);
3779     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3780     panda::JsiFastNativeScope fastNativeScope(vm);
3781 
3782     *result = nativeValue->IsBigInt64Array(vm);
3783     return napi_clear_last_error(env);
3784 }
3785 
napi_is_big_uint64_array(napi_env env,napi_value value,bool * result)3786 NAPI_EXTERN napi_status napi_is_big_uint64_array(napi_env env, napi_value value, bool* result)
3787 {
3788     CHECK_ENV(env);
3789     CHECK_ARG(env, value);
3790     CHECK_ARG(env, result);
3791 
3792     auto nativeValue = LocalValueFromJsValue(value);
3793     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3794     panda::JsiFastNativeScope fastNativeScope(vm);
3795 
3796     *result = nativeValue->IsBigUint64Array(vm);
3797     return napi_clear_last_error(env);
3798 }
3799 
napi_is_shared_array_buffer(napi_env env,napi_value value,bool * result)3800 NAPI_EXTERN napi_status napi_is_shared_array_buffer(napi_env env, napi_value value, bool* result)
3801 {
3802     CHECK_ENV(env);
3803     CHECK_ARG(env, value);
3804     CHECK_ARG(env, result);
3805 
3806     auto nativeValue = LocalValueFromJsValue(value);
3807     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3808     panda::JsiFastNativeScope fastNativeScope(vm);
3809 
3810     *result = nativeValue->IsSharedArrayBuffer(vm);
3811     return napi_clear_last_error(env);
3812 }
3813 
napi_get_stack_trace(napi_env env,std::string & stack)3814 NAPI_EXTERN napi_status napi_get_stack_trace(napi_env env, std::string& stack)
3815 {
3816     CHECK_ENV(env);
3817 
3818     auto engine = reinterpret_cast<NativeEngine*>(env);
3819     [[maybe_unused]] auto vm = engine->GetEcmaVm();
3820     std::string rawStack;
3821 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
3822     DFXJSNApi::BuildJsStackTrace(vm, rawStack);
3823     stack = engine->ExecuteTranslateBySourceMap(rawStack);
3824 #else
3825     HILOG_WARN("GetStacktrace env get stack failed");
3826 #endif
3827 
3828     return napi_clear_last_error(env);
3829 }
3830 
napi_get_hybrid_stack_trace(napi_env env,std::string & stack)3831 NAPI_EXTERN napi_status napi_get_hybrid_stack_trace(napi_env env, std::string& stack)
3832 {
3833     CHECK_ENV(env);
3834 
3835 #if defined(OHOS_PLATFORM) && !defined(is_arkui_x)
3836     auto engine = reinterpret_cast<NativeEngine*>(env);
3837     auto vm = engine->GetEcmaVm();
3838     stack = DumpHybridStack(vm);
3839 #else
3840     HILOG_WARN("GetHybridStacktrace env get hybrid stack failed");
3841 #endif
3842     return napi_clear_last_error(env);
3843 }
3844 
napi_object_get_keys(napi_env env,napi_value data,napi_value * result)3845 NAPI_EXTERN napi_status napi_object_get_keys(napi_env env, napi_value data, napi_value* result)
3846 {
3847     CHECK_ENV(env);
3848 
3849     auto nativeValue = LocalValueFromJsValue(data);
3850     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3851     panda::JsiFastNativeScope fastNativeScope(vm);
3852     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3853     auto obj = nativeValue->ToEcmaObject(vm);
3854     Local<panda::ArrayRef> arrayVal = obj->GetOwnEnumerablePropertyNames(vm);
3855 
3856     *result = JsValueFromLocalValue(arrayVal);
3857     return napi_clear_last_error(env);
3858 }
3859 
napi_queue_async_work_with_qos(napi_env env,napi_async_work work,napi_qos_t qos)3860 NAPI_EXTERN napi_status napi_queue_async_work_with_qos(napi_env env, napi_async_work work, napi_qos_t qos)
3861 {
3862     CHECK_ENV(env);
3863     CHECK_ARG(env, work);
3864 
3865     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
3866     asyncWork->QueueWithQos(qos);
3867     return napi_status::napi_ok;
3868 }
3869 
DetachFuncCallback(void * engine,void * object,void * hint,void * detachData)3870 void* DetachFuncCallback(void* engine, void* object, void* hint, void* detachData)
3871 {
3872     if (detachData == nullptr || (engine == nullptr || object ==nullptr)) {
3873         HILOG_ERROR("DetachFuncCallback params has nullptr");
3874         return nullptr;
3875     }
3876     DetachCallback detach = reinterpret_cast<DetachCallback>(detachData);
3877     void* detachVal = detach(reinterpret_cast<NativeEngine*>(engine), object, hint);
3878     return detachVal;
3879 }
3880 
AttachFuncCallback(void * engine,void * buffer,void * hint,void * attachData)3881 Local<panda::JSValueRef> AttachFuncCallback(void* engine, void* buffer, void* hint, void* attachData)
3882 {
3883     auto vm = reinterpret_cast<NativeEngine*>(engine)->GetEcmaVm();
3884     if (attachData == nullptr || (engine == nullptr || buffer ==nullptr)) {
3885         HILOG_ERROR("AttachFuncCallback params has nullptr");
3886         return panda::JSValueRef::Undefined(vm);
3887     }
3888     EscapeLocalScope scope(vm);
3889     Local<panda::JSValueRef> result = panda::JSValueRef::Undefined(vm);
3890     NapiAttachCallback attach = reinterpret_cast<NapiAttachCallback>(attachData);
3891     napi_value attachVal = attach(reinterpret_cast<napi_env>(engine), buffer, hint);
3892     if (attachVal == nullptr) {
3893         HILOG_WARN("AttachFunc return nullptr");
3894     } else {
3895         result = LocalValueFromJsValue(attachVal);
3896     }
3897     return scope.Escape(result);
3898 }
3899 
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)3900 NAPI_EXTERN napi_status napi_coerce_to_native_binding_object(napi_env env,
3901                                                              napi_value js_object,
3902                                                              napi_native_binding_detach_callback detach_cb,
3903                                                              napi_native_binding_attach_callback attach_cb,
3904                                                              void* native_object,
3905                                                              void* hint)
3906 {
3907     CHECK_ENV(env);
3908     CHECK_ARG(env, js_object);
3909     CHECK_ARG(env, detach_cb);
3910     CHECK_ARG(env, attach_cb);
3911     CHECK_ARG(env, native_object);
3912 
3913     auto jsValue = LocalValueFromJsValue(js_object);
3914     auto engine = reinterpret_cast<NativeEngine*>(env);
3915     auto vm = engine->GetEcmaVm();
3916     panda::JsiFastNativeScope fastNativeScope(vm);
3917 
3918     RETURN_STATUS_IF_FALSE(env, jsValue->IsObject(vm), napi_object_expected);
3919     auto obj = jsValue->ToEcmaObject(vm);
3920 
3921     panda::JSNApi::NativeBindingInfo* data = panda::JSNApi::NativeBindingInfo::CreateNewInstance();
3922     if (data == nullptr) {
3923         HILOG_ERROR("data is nullptr");
3924         return napi_set_last_error(env, napi_invalid_arg);
3925     }
3926     data->env = env;
3927     data->nativeValue = native_object;
3928     data->attachFunc = reinterpret_cast<void*>(AttachFuncCallback);
3929     data->attachData = reinterpret_cast<void*>(attach_cb);
3930     data->detachFunc = reinterpret_cast<void*>(DetachFuncCallback);
3931     data->detachData = reinterpret_cast<void*>(detach_cb);
3932     data->hint = hint;
3933 
3934     size_t nativeBindingSize = 7 * sizeof(void *); // 7 : params num
3935     Local<panda::NativePointerRef> value = panda::NativePointerRef::NewConcurrent(vm, data,
3936         [](void* env, void* data, void* info) {
3937             auto externalInfo = reinterpret_cast<panda::JSNApi::NativeBindingInfo*>(data);
3938             delete externalInfo;
3939         }, nullptr, nativeBindingSize);
3940 
3941     bool res = obj->ConvertToNativeBindingObject(vm, value);
3942     if (res) {
3943         return napi_clear_last_error(env);
3944     }
3945     return napi_status::napi_generic_failure;
3946 }
3947 
napi_get_print_string(napi_env env,napi_value value,std::string & result)3948 NAPI_EXTERN napi_status napi_get_print_string(napi_env env, napi_value value, std::string& result)
3949 {
3950     CHECK_ENV(env);
3951     CHECK_ARG(env, value);
3952 
3953     auto nativeValue = LocalValueFromJsValue(value);
3954     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3955     panda::JsiFastNativeScope fastNativeScope(vm);
3956 
3957     if (nativeValue->IsString(vm)) {
3958         Local<panda::StringRef> stringVal(nativeValue);
3959         result = stringVal->ToString(vm);
3960     }
3961     return napi_clear_last_error(env);
3962 }
3963 
napi_run_event_loop(napi_env env,napi_event_mode mode)3964 NAPI_EXTERN napi_status napi_run_event_loop(napi_env env, napi_event_mode mode)
3965 {
3966     CHECK_ENV(env);
3967 
3968     if (mode < napi_event_mode_default || mode > napi_event_mode_nowait) {
3969         HILOG_ERROR("invalid mode %{public}d", static_cast<int32_t>(mode));
3970         return napi_status::napi_invalid_arg;
3971     }
3972 
3973     auto nativeEngine = reinterpret_cast<NativeEngine*>(env);
3974     auto result = nativeEngine->RunEventLoop(mode);
3975     if (result != napi_status::napi_ok) {
3976         HILOG_ERROR("failed due to error %{public}d", static_cast<int32_t>(result));
3977         return napi_set_last_error(env, result);
3978     }
3979 
3980     return napi_clear_last_error(env);
3981 }
3982 
napi_stop_event_loop(napi_env env)3983 NAPI_EXTERN napi_status napi_stop_event_loop(napi_env env)
3984 {
3985     CHECK_ENV(env);
3986 
3987     auto nativeEngine = reinterpret_cast<NativeEngine*>(env);
3988     auto result = nativeEngine->StopEventLoop();
3989     if (result != napi_status::napi_ok) {
3990         HILOG_ERROR("stop event loop failed due to error %{public}d", static_cast<int32_t>(result));
3991         return napi_set_last_error(env, result);
3992     }
3993     return napi_clear_last_error(env);
3994 }
3995 
napi_create_ark_runtime(napi_env * env)3996 NAPI_EXTERN napi_status napi_create_ark_runtime(napi_env* env)
3997 {
3998     if (NativeCreateEnv::g_createNapiEnvCallback == nullptr) {
3999         HILOG_ERROR("invalid create callback");
4000         return napi_status::napi_invalid_arg;
4001     }
4002     napi_status result = NativeCreateEnv::g_createNapiEnvCallback(env);
4003     if (result == napi_ok) {
4004         auto vm = reinterpret_cast<NativeEngine*>(*env)->GetEcmaVm();
4005         panda::JSNApi::SetExecuteBufferMode(vm);
4006     }
4007     return result;
4008 }
4009 
napi_destroy_ark_runtime(napi_env * env)4010 NAPI_EXTERN napi_status napi_destroy_ark_runtime(napi_env* env)
4011 {
4012     if (NativeCreateEnv::g_destroyNapiEnvCallback == nullptr) {
4013         HILOG_ERROR("invalid destroy callback");
4014         return napi_status::napi_invalid_arg;
4015     }
4016     return NativeCreateEnv::g_destroyNapiEnvCallback(env);
4017 }
4018 
napi_is_concurrent_function(napi_env env,napi_value value,bool * result)4019 NAPI_EXTERN napi_status napi_is_concurrent_function(napi_env env, napi_value value, bool* result)
4020 {
4021     CHECK_ENV(env);
4022     CHECK_ARG(env, value);
4023     CHECK_ARG(env, result);
4024 
4025     auto nativeValue = LocalValueFromJsValue(value);
4026     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
4027     panda::JsiFastNativeScope fastNativeScope(vm);
4028 
4029     *result = nativeValue->IsConcurrentFunction(vm);
4030     return napi_clear_last_error(env);
4031 }
4032 
napi_call_threadsafe_function_with_priority(napi_threadsafe_function func,void * data,napi_task_priority priority,bool isTail)4033 NAPI_EXTERN napi_status napi_call_threadsafe_function_with_priority(napi_threadsafe_function func,
4034                                                                     void *data,
4035                                                                     napi_task_priority priority,
4036                                                                     bool isTail)
4037 {
4038     CHECK_ENV(func);
4039 
4040     if (priority < napi_priority_immediate || priority > napi_priority_idle) {
4041         HILOG_ERROR("invalid priority %{public}d", static_cast<int32_t>(priority));
4042         return napi_status::napi_invalid_arg;
4043     }
4044     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
4045     int32_t innerPriority = static_cast<int32_t>(priority);
4046     auto res = safeAsyncWork->PostTask(data, innerPriority, isTail);
4047     if (res != napi_ok) {
4048         HILOG_ERROR("post task failed due to error %{public}d", res);
4049     }
4050     return res;
4051 }
4052 
napi_send_event(napi_env env,const std::function<void ()> cb,napi_event_priority priority)4053 NAPI_EXTERN napi_status napi_send_event(napi_env env, const std::function<void()> cb, napi_event_priority priority)
4054 {
4055     CHECK_ENV(env);
4056 
4057     if (priority < napi_eprio_vip || priority > napi_eprio_idle) {
4058         HILOG_ERROR("invalid priority %{public}d", static_cast<int32_t>(priority));
4059         return napi_status::napi_invalid_arg;
4060     }
4061     NativeEngine *eng = reinterpret_cast<NativeEngine *>(env);
4062     if (NativeEngine::IsAlive(eng)) {
4063         return eng->SendEvent(cb, priority);
4064     } else {
4065         return napi_status::napi_closing;
4066     }
4067 }
4068 
napi_open_fast_native_scope(napi_env env,napi_fast_native_scope * scope)4069 NAPI_EXTERN napi_status napi_open_fast_native_scope(napi_env env, napi_fast_native_scope* scope)
4070 {
4071     CHECK_ENV(env);
4072     CHECK_ARG(env, scope);
4073 
4074     auto engine = reinterpret_cast<NativeEngine*>(env);
4075     *scope = reinterpret_cast<napi_fast_native_scope>(new panda::JsiFastNativeScope(engine->GetEcmaVm()));
4076     return napi_clear_last_error(env);
4077 }
4078 
napi_close_fast_native_scope(napi_env env,napi_fast_native_scope scope)4079 NAPI_EXTERN napi_status napi_close_fast_native_scope(napi_env env, napi_fast_native_scope scope)
4080 {
4081     CHECK_ENV(env);
4082     CHECK_ARG(env, scope);
4083 
4084     delete reinterpret_cast<panda::JsiFastNativeScope*>(scope);
4085     return napi_clear_last_error(env);
4086 }
4087 
napi_get_shared_array_buffer_info(napi_env env,napi_value arraybuffer,void ** data,size_t * byte_length)4088 NAPI_EXTERN napi_status napi_get_shared_array_buffer_info(napi_env env,
4089                                                           napi_value arraybuffer,
4090                                                           void** data,
4091                                                           size_t* byte_length)
4092 {
4093     CHECK_ENV(env);
4094     CHECK_ARG(env, arraybuffer);
4095     CHECK_ARG(env, byte_length);
4096 
4097     auto nativeValue = LocalValueFromJsValue(arraybuffer);
4098     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
4099     panda::JsiFastNativeScope fastNativeScope(vm);
4100     if (LIKELY(nativeValue->IsSharedArrayBuffer(vm))) {
4101         Local<panda::ArrayBufferRef> res(nativeValue);
4102         if (data != nullptr) {
4103             *data = res->GetBuffer(vm);
4104         }
4105         *byte_length = res->ByteLength(vm);
4106     } else {
4107         return napi_set_last_error(env, napi_arraybuffer_expected);
4108     }
4109 
4110     return napi_clear_last_error(env);
4111 }
4112 
napi_is_bitvector(napi_env env,napi_value value,bool * result)4113 NAPI_EXTERN napi_status napi_is_bitvector(napi_env env, napi_value value, bool* result)
4114 {
4115     CHECK_ENV(env);
4116     CHECK_ARG(env, value);
4117     CHECK_ARG(env, result);
4118 
4119     auto nativeValue = LocalValueFromJsValue(value);
4120     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
4121     panda::JsiFastNativeScope fastNativeScope(vm);
4122 
4123     *result = nativeValue->IsBitVector(vm);
4124 
4125     return napi_clear_last_error(env);
4126 }
4127