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