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