• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef NAPI_EXPERIMENTAL
16 #define NAPI_EXPERIMENTAL
17 #endif
18 
19 #ifdef ENABLE_HITRACE
20 #include <sys/prctl.h>
21 #endif
22 
23 #include "ecmascript/napi/include/jsnapi.h"
24 #include "native_api_internal.h"
25 #include "native_engine/impl/ark/ark_native_engine.h"
26 #include "native_engine/impl/ark/ark_native_reference.h"
27 #include "native_engine/native_property.h"
28 #include "native_engine/native_utils.h"
29 #include "native_engine/native_value.h"
30 #include "securec.h"
31 #include "utils/log.h"
32 #ifdef ENABLE_HITRACE
33 #include "hitrace_meter.h"
34 #endif
35 
36 using panda::ArrayRef;
37 using panda::ArrayBufferRef;
38 using panda::BigIntRef;
39 using panda::BooleanRef;
40 using panda::BufferRef;
41 using panda::DateRef;
42 using panda::DataViewRef;
43 using panda::EscapeLocalScope;
44 using panda::FunctionRef;
45 using panda::Global;
46 using panda::IntegerRef;
47 using panda::JSNApi;
48 using panda::JsiRuntimeCallInfo;
49 using panda::Local;
50 using panda::LocalScope;
51 using panda::NativePointerRef;
52 using panda::NumberRef;
53 using panda::ObjectRef;
54 using panda::PrimitiveRef;
55 using panda::PromiseCapabilityRef;
56 using panda::PromiseRef;
57 using panda::PropertyAttribute;
58 using panda::StringRef;
59 using panda::SymbolRef;
60 using panda::TypedArrayRef;
61 using panda::ecmascript::EcmaVM;
62 
63 static constexpr size_t MAX_BYTE_LENGTH = 2097152;
64 static constexpr size_t ONEMIB_BYTE_SIZE = 1048576;
65 static constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
66 
67 class HandleScopeWrapper {
68 public:
HandleScopeWrapper(NativeEngine * engine)69     explicit HandleScopeWrapper(NativeEngine* engine) : scope_(engine->GetEcmaVm()) {}
70 
71 private:
72     LocalScope scope_;
73 };
74 
75 class EscapableHandleScopeWrapper {
76 public:
EscapableHandleScopeWrapper(NativeEngine * engine)77     explicit EscapableHandleScopeWrapper(NativeEngine* engine)
78         : scope_(engine->GetEcmaVm()), escapeCalled_(false) {}
79 
IsEscapeCalled() const80     bool IsEscapeCalled() const
81     {
82         return escapeCalled_;
83     }
84 
85     template<typename T>
Escape(Local<T> value)86     Local<T> Escape(Local<T> value)
87     {
88         escapeCalled_ = true;
89         return scope_.Escape(value);
90     }
91 
92 private:
93     EscapeLocalScope scope_;
94     bool escapeCalled_;
95 };
96 
HandleScopeToNapiHandleScope(HandleScopeWrapper * s)97 inline napi_handle_scope HandleScopeToNapiHandleScope(HandleScopeWrapper* s)
98 {
99     return reinterpret_cast<napi_handle_scope>(s);
100 }
101 
NapiHandleScopeToHandleScope(napi_handle_scope s)102 inline HandleScopeWrapper* NapiHandleScopeToHandleScope(napi_handle_scope s)
103 {
104     return reinterpret_cast<HandleScopeWrapper*>(s);
105 }
106 
EscapableHandleScopeToNapiEscapableHandleScope(EscapableHandleScopeWrapper * s)107 inline napi_escapable_handle_scope EscapableHandleScopeToNapiEscapableHandleScope(EscapableHandleScopeWrapper* s)
108 {
109     return reinterpret_cast<napi_escapable_handle_scope>(s);
110 }
111 
NapiEscapableHandleScopeToEscapableHandleScope(napi_escapable_handle_scope s)112 inline EscapableHandleScopeWrapper* NapiEscapableHandleScopeToEscapableHandleScope(napi_escapable_handle_scope s)
113 {
114     return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
115 }
116 
napi_get_last_error_info(napi_env env,const napi_extended_error_info ** result)117 NAPI_EXTERN napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info** result)
118 {
119     CHECK_ENV(env);
120     CHECK_ARG(env, result);
121 
122     *result = reinterpret_cast<napi_extended_error_info*>(reinterpret_cast<NativeEngine*>(env)->GetLastError());
123     if ((*result)->error_code == napi_ok) {
124         napi_clear_last_error(env);
125     }
126 
127     return napi_ok;
128 }
129 
130 // Getters for defined singletons
napi_get_undefined(napi_env env,napi_value * result)131 NAPI_EXTERN napi_status napi_get_undefined(napi_env env, napi_value* result)
132 {
133     CHECK_ENV(env);
134     CHECK_ARG(env, result);
135 
136     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
137     Local<panda::PrimitiveRef> value = panda::JSValueRef::Undefined(vm);
138     *result = JsValueFromLocalValue(value);
139 
140     return napi_clear_last_error(env);
141 }
142 
napi_get_null(napi_env env,napi_value * result)143 NAPI_EXTERN napi_status napi_get_null(napi_env env, napi_value* result)
144 {
145     CHECK_ENV(env);
146     CHECK_ARG(env, result);
147 
148     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
149     Local<panda::PrimitiveRef> value = panda::JSValueRef::Null(vm);
150     *result = JsValueFromLocalValue(value);
151 
152     return napi_clear_last_error(env);
153 }
154 
napi_get_global(napi_env env,napi_value * result)155 NAPI_EXTERN napi_status napi_get_global(napi_env env, napi_value* result)
156 {
157     CHECK_ENV(env);
158     CHECK_ARG(env, result);
159 
160     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
161     Local<panda::ObjectRef> value = panda::JSNApi::GetGlobalObject(vm);
162     *result = JsValueFromLocalValue(value);
163 
164     return napi_clear_last_error(env);
165 }
166 
napi_get_boolean(napi_env env,bool value,napi_value * result)167 NAPI_EXTERN napi_status napi_get_boolean(napi_env env, bool value, napi_value* result)
168 {
169     CHECK_ENV(env);
170     CHECK_ARG(env, result);
171 
172     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
173     if (value) {
174         *result = JsValueFromLocalValue(panda::JSValueRef::True(vm));
175     } else {
176         *result = JsValueFromLocalValue(panda::JSValueRef::False(vm));
177     }
178 
179     return napi_clear_last_error(env);
180 }
181 
182 // Methods to create Primitive types/Objects
napi_create_object(napi_env env,napi_value * result)183 NAPI_EXTERN napi_status napi_create_object(napi_env env, napi_value* result)
184 {
185     CHECK_ENV(env);
186     CHECK_ARG(env, result);
187 
188     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
189     Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
190     *result = JsValueFromLocalValue(object);
191 
192     return napi_clear_last_error(env);
193 }
194 
195 // Create JSObject with initial properties given by descriptors, note that property key must be String, and
196 // 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)197 NAPI_EXTERN napi_status napi_create_object_with_properties(napi_env env, napi_value* result, size_t property_count,
198                                                            const napi_property_descriptor* properties)
199 {
200     CHECK_ENV(env);
201     CHECK_ARG(env, result);
202 
203     Local<panda::ObjectRef> object;
204     if (property_count <= panda::ObjectRef::MAX_PROPERTIES_ON_STACK) {
205         char attrs[sizeof(PropertyAttribute) * panda::ObjectRef::MAX_PROPERTIES_ON_STACK];
206         char keys[sizeof(Local<panda::JSValueRef>) * panda::ObjectRef::MAX_PROPERTIES_ON_STACK];
207         object = NapiCreateObjectWithProperties(env, property_count, properties,
208                                                 reinterpret_cast<Local<panda::JSValueRef> *>(keys),
209                                                 reinterpret_cast<PropertyAttribute *>(attrs));
210     } else {
211         void *attrs = malloc(sizeof(PropertyAttribute) * property_count);
212         void *keys = malloc(sizeof(Local<panda::JSValueRef>) * property_count);
213         if (attrs != nullptr && keys != nullptr) {
214             object = NapiCreateObjectWithProperties(env, property_count, properties,
215                                                     reinterpret_cast<Local<panda::JSValueRef> *>(keys),
216                                                     reinterpret_cast<PropertyAttribute *>(attrs));
217         } else {
218             auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
219             object = panda::JSValueRef::Undefined(vm);
220             napi_throw_error(env, nullptr, "malloc failed in napi_create_object_with_properties");
221         }
222         if (attrs != nullptr) {
223             free(attrs);
224         }
225         if (keys != nullptr) {
226             free(keys);
227         }
228     }
229     *result = JsValueFromLocalValue(object);
230 
231     return napi_clear_last_error(env);
232 }
233 
234 // Create JSObject with initial properties given by keys and values, note that property key must be String, and
235 // 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)236 NAPI_EXTERN napi_status napi_create_object_with_named_properties(napi_env env, napi_value* result,
237                                                                  size_t property_count, const char** keys,
238                                                                  const napi_value* values)
239 {
240     CHECK_ENV(env);
241     CHECK_ARG(env, result);
242 
243     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
244     Local<panda::ObjectRef> object = panda::ObjectRef::NewWithNamedProperties(vm, property_count, keys,
245         reinterpret_cast<const Local<JSValueRef> *>(values));
246     *result = JsValueFromLocalValue(object);
247 
248     return napi_clear_last_error(env);
249 }
250 
napi_create_array(napi_env env,napi_value * result)251 NAPI_EXTERN napi_status napi_create_array(napi_env env, napi_value* result)
252 {
253     CHECK_ENV(env);
254     CHECK_ARG(env, result);
255 
256     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
257     Local<panda::ArrayRef> object = panda::ArrayRef::New(vm, 0);
258     *result = JsValueFromLocalValue(object);
259 
260     return napi_clear_last_error(env);
261 }
262 
napi_create_array_with_length(napi_env env,size_t length,napi_value * result)263 NAPI_EXTERN napi_status napi_create_array_with_length(napi_env env, size_t length, napi_value* result)
264 {
265     CHECK_ENV(env);
266     CHECK_ARG(env, result);
267 
268     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
269     Local<panda::ArrayRef> object = panda::ArrayRef::New(vm, length);
270     *result = JsValueFromLocalValue(object);
271 
272     return napi_clear_last_error(env);
273 }
274 
napi_create_double(napi_env env,double value,napi_value * result)275 NAPI_EXTERN napi_status napi_create_double(napi_env env, double value, napi_value* result)
276 {
277     CHECK_ENV(env);
278     CHECK_ARG(env, result);
279 
280     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
281     Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
282     *result = JsValueFromLocalValue(object);
283 
284     return napi_clear_last_error(env);
285 }
286 
napi_create_int32(napi_env env,int32_t value,napi_value * result)287 NAPI_EXTERN napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
288 {
289     CHECK_ENV(env);
290     CHECK_ARG(env, result);
291 
292     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
293     Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
294     *result = JsValueFromLocalValue(object);
295 
296     return napi_clear_last_error(env);
297 }
298 
napi_create_uint32(napi_env env,uint32_t value,napi_value * result)299 NAPI_EXTERN napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result)
300 {
301     CHECK_ENV(env);
302     CHECK_ARG(env, result);
303 
304     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
305     Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
306     *result = JsValueFromLocalValue(object);
307 
308     return napi_clear_last_error(env);
309 }
310 
napi_create_int64(napi_env env,int64_t value,napi_value * result)311 NAPI_EXTERN napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result)
312 {
313     CHECK_ENV(env);
314     CHECK_ARG(env, result);
315 
316     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
317     Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
318     *result = JsValueFromLocalValue(object);
319 
320     return napi_clear_last_error(env);
321 }
322 
napi_create_string_latin1(napi_env env,const char * str,size_t length,napi_value * result)323 NAPI_EXTERN napi_status napi_create_string_latin1(napi_env env, const char* str, size_t length, napi_value* result)
324 {
325     CHECK_ENV(env);
326     CHECK_ARG(env, str);
327     CHECK_ARG(env, result);
328 
329     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
330     Local<panda::StringRef> object = panda::StringRef::NewFromUtf8(
331         vm, str, (length == NAPI_AUTO_LENGTH) ? strlen(str) : length);
332     *result = JsValueFromLocalValue(object);
333 
334     return napi_clear_last_error(env);
335 }
336 
napi_create_string_utf8(napi_env env,const char * str,size_t length,napi_value * result)337 NAPI_EXTERN napi_status napi_create_string_utf8(napi_env env, const char* str, size_t length, napi_value* result)
338 {
339     CHECK_ENV(env);
340     CHECK_ARG(env, str);
341     CHECK_ARG(env, result);
342 
343     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
344     Local<panda::StringRef> object = panda::StringRef::NewFromUtf8(
345         vm, str, (length == NAPI_AUTO_LENGTH) ? strlen(str) : length);
346     *result = JsValueFromLocalValue(object);
347 
348     return napi_clear_last_error(env);
349 }
350 
napi_create_string_utf16(napi_env env,const char16_t * str,size_t length,napi_value * result)351 NAPI_EXTERN napi_status napi_create_string_utf16(
352     napi_env env, const char16_t* str, size_t length, napi_value* result)
353 {
354     CHECK_ENV(env);
355     CHECK_ARG(env, str);
356     CHECK_ARG(env, result);
357     RETURN_STATUS_IF_FALSE(env, (length == NAPI_AUTO_LENGTH) || (length <= INT_MAX && length >= 0), napi_invalid_arg);
358 
359     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
360     int char16Length = static_cast<int>(std::char_traits<char16_t>::length(str));
361     Local<panda::StringRef> object = panda::StringRef::NewFromUtf16(
362         vm, str, (length == NAPI_AUTO_LENGTH) ? char16Length : length);
363     *result = JsValueFromLocalValue(object);
364 
365     return napi_clear_last_error(env);
366 }
367 
napi_create_symbol(napi_env env,napi_value description,napi_value * result)368 NAPI_EXTERN napi_status napi_create_symbol(napi_env env, napi_value description, napi_value* result)
369 {
370     CHECK_ENV(env);
371     CHECK_ARG(env, result);
372 
373     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
374     panda::Local<panda::JSValueRef> object = panda::JSValueRef::Undefined(vm);
375     if (description == nullptr) {
376         const char* str = "";
377         object = panda::StringRef::NewFromUtf8(vm, str, 0);
378     } else {
379         object = LocalValueFromJsValue(description);
380     }
381     RETURN_STATUS_IF_FALSE(env, object->IsString(), napi_invalid_arg);
382     Local<panda::SymbolRef> symbol = panda::SymbolRef::New(vm, object);
383     *result = JsValueFromLocalValue(symbol);
384 
385     return napi_clear_last_error(env);
386 }
387 
napi_create_function(napi_env env,const char * utf8name,size_t length,napi_callback cb,void * data,napi_value * result)388 NAPI_EXTERN napi_status napi_create_function(napi_env env,
389                                              const char* utf8name,
390                                              size_t length,
391                                              napi_callback cb,
392                                              void* data,
393                                              napi_value* result)
394 {
395     NAPI_PREAMBLE(env);
396     CHECK_ARG(env, cb);
397     CHECK_ARG(env, result);
398 
399     auto vm = const_cast<EcmaVM*>(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
400     EscapeLocalScope scope(vm);
401     auto callback = reinterpret_cast<NapiNativeCallback>(cb);
402     const char* name = "defaultName";
403     NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
404     if (funcInfo == nullptr) {
405         HILOG_ERROR("funcInfo is nullptr");
406         return napi_set_last_error(env, napi_invalid_arg);
407     }
408     funcInfo->env = env;
409     funcInfo->callback = callback;
410     funcInfo->data = data;
411 
412     Local<panda::FunctionRef> fn = panda::FunctionRef::New(vm, ArkNativeFunctionCallBack,
413                                                            [](void* externalPointer, void* data) {
414                                                                 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
415                                                                 if (info != nullptr) {
416                                                                     delete info;
417                                                                 }
418                                                            },
419                                                            reinterpret_cast<void*>(funcInfo), true);
420     Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, utf8name != nullptr ? utf8name : name);
421     fn->SetName(vm, fnName);
422     *result = JsValueFromLocalValue(scope.Escape(fn));
423     return GET_RETURN_STATUS(env);
424 }
425 
napi_create_error(napi_env env,napi_value code,napi_value msg,napi_value * result)426 NAPI_EXTERN napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value* result)
427 {
428     CHECK_ENV(env);
429     CHECK_ARG(env, msg);
430     CHECK_ARG(env, result);
431 
432     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
433     Local<panda::JSValueRef> codeValue = panda::JSValueRef::Undefined(vm);
434     if (code != nullptr) {
435         codeValue = LocalValueFromJsValue(code);
436         RETURN_STATUS_IF_FALSE(env, codeValue->IsString() || codeValue->IsNumber(), napi_invalid_arg);
437     }
438 
439     auto msgValue = LocalValueFromJsValue(msg);
440     RETURN_STATUS_IF_FALSE(env, msgValue->IsString(), napi_invalid_arg);
441 
442     Local<panda::JSValueRef> errorVal = panda::Exception::Error(vm, msgValue);
443     if (code != nullptr) {
444         Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
445         Local<panda::ObjectRef> errorObj(errorVal);
446         errorObj->Set(vm, codeKey, codeValue);
447     }
448     *result = JsValueFromLocalValue(errorVal);
449 
450     return napi_clear_last_error(env);
451 }
452 
napi_create_type_error(napi_env env,napi_value code,napi_value msg,napi_value * result)453 NAPI_EXTERN napi_status napi_create_type_error(napi_env env, napi_value code, napi_value msg, napi_value* result)
454 {
455     CHECK_ENV(env);
456     CHECK_ARG(env, msg);
457     CHECK_ARG(env, result);
458 
459     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
460     Local<panda::JSValueRef> codeValue = panda::JSValueRef::Undefined(vm);
461     if (code != nullptr) {
462         codeValue = LocalValueFromJsValue(code);
463         RETURN_STATUS_IF_FALSE(env, codeValue->IsString() || codeValue->IsNumber(), napi_invalid_arg);
464     }
465     auto msgValue = LocalValueFromJsValue(msg);
466     RETURN_STATUS_IF_FALSE(env, msgValue->IsString(), napi_invalid_arg);
467 
468     Local<panda::JSValueRef> errorVal = panda::Exception::Error(vm, msgValue);
469     if (code != nullptr) {
470         Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
471         Local<panda::ObjectRef> errorObj(errorVal);
472         errorObj->Set(vm, codeKey, codeValue);
473     }
474     *result = JsValueFromLocalValue(errorVal);
475 
476     return napi_clear_last_error(env);
477 }
478 
napi_create_range_error(napi_env env,napi_value code,napi_value msg,napi_value * result)479 NAPI_EXTERN napi_status napi_create_range_error(napi_env env, napi_value code, napi_value msg, napi_value* result)
480 {
481     CHECK_ENV(env);
482     CHECK_ARG(env, msg);
483     CHECK_ARG(env, result);
484 
485     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
486     Local<panda::JSValueRef> codeValue = panda::JSValueRef::Undefined(vm);
487 
488     if (code != nullptr) {
489         codeValue = LocalValueFromJsValue(code);
490         RETURN_STATUS_IF_FALSE(env, codeValue->IsString() || codeValue->IsNumber(), napi_invalid_arg);
491     }
492     auto msgValue = LocalValueFromJsValue(msg);
493     RETURN_STATUS_IF_FALSE(env, msgValue->IsString(), napi_invalid_arg);
494 
495     Local<panda::JSValueRef> errorVal = panda::Exception::Error(vm, msgValue);
496     if (code != nullptr) {
497         Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
498         Local<panda::ObjectRef> errorObj(errorVal);
499         errorObj->Set(vm, codeKey, codeValue);
500     }
501     *result = JsValueFromLocalValue(errorVal);
502 
503     return napi_clear_last_error(env);
504 }
505 
506 // Methods to get the native napi_value from Primitive type
napi_typeof(napi_env env,napi_value value,napi_valuetype * result)507 NAPI_EXTERN napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
508 {
509     CHECK_ENV(env);
510     CHECK_ARG(env, value);
511     CHECK_ARG(env, result);
512 
513     auto valueObj = LocalValueFromJsValue(value);
514     napi_valuetype resultType;
515     if (valueObj->IsNumber()) {
516         resultType = napi_number;
517     } else if (valueObj->IsString()) {
518         resultType = napi_string;
519     } else if (valueObj->IsFunction()) {
520         resultType = napi_function;
521     } else if (valueObj->IsNativePointer()) {
522         resultType = napi_external;
523     } else if (valueObj->IsNull()) {
524         resultType = napi_null;
525     } else if (valueObj->IsBoolean()) {
526         resultType = napi_boolean;
527     } else if (valueObj->IsUndefined()) {
528         resultType = napi_undefined;
529     } else if (valueObj->IsSymbol()) {
530         resultType = napi_symbol;
531     } else if (valueObj->IsBigInt()) {
532         resultType = napi_bigint;
533     } else if (valueObj->IsObject()) {
534         resultType = napi_object;
535     } else {
536         resultType = napi_undefined;
537     }
538     *result = resultType;
539     return napi_clear_last_error(env);
540 }
541 
napi_get_value_double(napi_env env,napi_value value,double * result)542 NAPI_EXTERN napi_status napi_get_value_double(napi_env env, napi_value value, double* result)
543 {
544     CHECK_ENV(env);
545     CHECK_ARG(env, value);
546     CHECK_ARG(env, result);
547 
548     auto nativeValue = LocalValueFromJsValue(value);
549     RETURN_STATUS_IF_FALSE(env, nativeValue->IsNumber(), napi_number_expected);
550     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
551     Local<panda::NumberRef> NumberVal = nativeValue->ToNumber(vm);
552     *result = NumberVal->Value();
553     return napi_clear_last_error(env);
554 }
555 
napi_get_value_int32(napi_env env,napi_value value,int32_t * result)556 NAPI_EXTERN napi_status napi_get_value_int32(napi_env env, napi_value value, int32_t* result)
557 {
558     CHECK_ENV(env);
559     CHECK_ARG(env, value);
560     CHECK_ARG(env, result);
561 
562     auto nativeValue = LocalValueFromJsValue(value);
563     RETURN_STATUS_IF_FALSE(env, nativeValue->IsNumber(), napi_number_expected);
564     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
565     *result = nativeValue->Int32Value(vm);
566 
567     return napi_clear_last_error(env);
568 }
569 
napi_get_value_uint32(napi_env env,napi_value value,uint32_t * result)570 NAPI_EXTERN napi_status napi_get_value_uint32(napi_env env, napi_value value, uint32_t* result)
571 {
572     CHECK_ENV(env);
573     CHECK_ARG(env, value);
574     CHECK_ARG(env, result);
575 
576     auto nativeValue = LocalValueFromJsValue(value);
577     RETURN_STATUS_IF_FALSE(env, nativeValue->IsNumber(), napi_number_expected);
578     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
579     *result = nativeValue->Uint32Value(vm);
580     return napi_clear_last_error(env);
581 }
582 
napi_get_value_int64(napi_env env,napi_value value,int64_t * result)583 NAPI_EXTERN napi_status napi_get_value_int64(napi_env env, napi_value value, int64_t* result)
584 {
585     CHECK_ENV(env);
586     CHECK_ARG(env, value);
587     CHECK_ARG(env, result);
588 
589     auto nativeValue = LocalValueFromJsValue(value);
590     RETURN_STATUS_IF_FALSE(env, nativeValue->IsNumber(), napi_number_expected);
591     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
592     *result = nativeValue->IntegerValue(vm);
593     return napi_clear_last_error(env);
594 }
595 
napi_get_value_bool(napi_env env,napi_value value,bool * result)596 NAPI_EXTERN napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result)
597 {
598     CHECK_ENV(env);
599     CHECK_ARG(env, value);
600     CHECK_ARG(env, result);
601 
602     Local<panda::JSValueRef> val = LocalValueFromJsValue(value);
603     RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
604     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
605     Local<panda::BooleanRef> boolVal = val->ToBoolean(vm);
606     *result = boolVal->Value();
607     return napi_clear_last_error(env);
608 }
609 
610 // 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)611 NAPI_EXTERN napi_status napi_get_value_string_latin1(napi_env env,
612                                                      napi_value value,
613                                                      char* buf,
614                                                      size_t bufsize,
615                                                      size_t* result)
616 {
617     CHECK_ENV(env);
618     CHECK_ARG(env, value);
619     CHECK_ARG(env, result);
620 
621     auto nativeValue = LocalValueFromJsValue(value);
622     RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(), napi_string_expected);
623     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
624     Local<panda::StringRef> stringVal = nativeValue->ToString(vm);
625     if (buf == nullptr) {
626         *result = stringVal->Length();
627     } else if (bufsize != 0) {
628         int copied = stringVal->WriteLatin1(buf, bufsize);
629         buf[copied] = '\0';
630         *result = copied;
631     } else {
632         *result = 0;
633     }
634 
635     return napi_clear_last_error(env);
636 }
637 
638 // 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)639 NAPI_EXTERN napi_status napi_get_value_string_utf8(napi_env env,
640                                                    napi_value value,
641                                                    char* buf,
642                                                    size_t bufsize,
643                                                    size_t* result)
644 {
645     CHECK_ENV(env);
646     CHECK_ARG(env, value);
647     CHECK_ARG(env, result);
648 
649     auto nativeValue = LocalValueFromJsValue(value);
650     RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(), napi_string_expected);
651     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
652     Local<panda::StringRef> stringVal = nativeValue->ToString(vm);
653     if (buf == nullptr) {
654         *result = stringVal->Utf8Length(vm) - 1;
655     } else if (bufsize != 0) {
656         int copied = stringVal->WriteUtf8(buf, bufsize - 1, true) - 1;
657         buf[copied] = '\0';
658         *result = copied;
659     } else {
660         *result = 0;
661     }
662 
663     return napi_clear_last_error(env);
664 }
665 
napi_get_value_string_utf16(napi_env env,napi_value value,char16_t * buf,size_t bufsize,size_t * result)666 NAPI_EXTERN napi_status napi_get_value_string_utf16(napi_env env,
667                                                     napi_value value,
668                                                     char16_t* buf,
669                                                     size_t bufsize,
670                                                     size_t* result)
671 {
672     CHECK_ENV(env);
673     CHECK_ARG(env, value);
674     CHECK_ARG(env, result);
675 
676     auto nativeValue = LocalValueFromJsValue(value);
677     RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(), napi_string_expected);
678     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
679     Local<panda::StringRef> stringVal = nativeValue->ToString(vm);
680     if (buf == nullptr) {
681         *result = stringVal->Length();
682     } else if (bufsize == 1) {
683         buf[0] = '\0';
684         *result = 0;
685     } else if (bufsize != 0) {
686         int copied = stringVal->WriteUtf16(buf, bufsize - 1); // bufsize - 1 : reserve the position of buf "\0"
687         buf[copied] = '\0';
688         *result = copied;
689     } else {
690         *result = 0;
691     }
692 
693     return napi_clear_last_error(env);
694 }
695 
696 // Methods to coerce values
697 // These APIs may execute user scripts
napi_coerce_to_bool(napi_env env,napi_value value,napi_value * result)698 NAPI_EXTERN napi_status napi_coerce_to_bool(napi_env env, napi_value value, napi_value* result)
699 {
700     NAPI_PREAMBLE(env);
701     CHECK_ARG(env, value);
702     CHECK_ARG(env, result);
703 
704     Local<panda::JSValueRef> val = LocalValueFromJsValue(value);
705     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
706     Local<panda::BooleanRef> boolVal = val->ToBoolean(vm);
707     *result = JsValueFromLocalValue(boolVal);
708 
709     return napi_clear_last_error(env);
710 }
711 
napi_coerce_to_number(napi_env env,napi_value value,napi_value * result)712 NAPI_EXTERN napi_status napi_coerce_to_number(napi_env env, napi_value value, napi_value* result)
713 {
714     CHECK_ENV(env);
715     CHECK_ARG(env, value);
716     CHECK_ARG(env, result);
717 
718     auto nativeValue = LocalValueFromJsValue(value);
719     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
720     *result = JsValueFromLocalValue(nativeValue->ToNumber(vm));
721 
722     return napi_clear_last_error(env);
723 }
724 
napi_coerce_to_object(napi_env env,napi_value value,napi_value * result)725 NAPI_EXTERN napi_status napi_coerce_to_object(napi_env env, napi_value value, napi_value* result)
726 {
727     CHECK_ENV(env);
728     CHECK_ARG(env, value);
729     CHECK_ARG(env, result);
730 
731     auto nativeValue = LocalValueFromJsValue(value);
732     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
733     *result = JsValueFromLocalValue(nativeValue->ToObject(vm));
734 
735     return napi_clear_last_error(env);
736 }
737 
napi_coerce_to_string(napi_env env,napi_value value,napi_value * result)738 NAPI_EXTERN napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result)
739 {
740     CHECK_ENV(env);
741     CHECK_ARG(env, value);
742     CHECK_ARG(env, result);
743 
744     auto nativeValue = LocalValueFromJsValue(value);
745     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
746     *result = JsValueFromLocalValue(nativeValue->ToString(vm));
747 
748     return napi_clear_last_error(env);
749 }
750 
751 // Methods to work with Objects
napi_get_prototype(napi_env env,napi_value object,napi_value * result)752 NAPI_EXTERN napi_status napi_get_prototype(napi_env env, napi_value object, napi_value* result)
753 {
754     NAPI_PREAMBLE(env);
755     CHECK_ARG(env, object);
756     CHECK_ARG(env, result);
757 
758     auto nativeValue = LocalValueFromJsValue(object);
759     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
760     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
761     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
762     Local<panda::JSValueRef> val = obj->GetPrototype(vm);
763     *result = JsValueFromLocalValue(val);
764 
765     return GET_RETURN_STATUS(env);
766 }
767 
napi_get_property_names(napi_env env,napi_value object,napi_value * result)768 NAPI_EXTERN napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result)
769 {
770     CHECK_ENV(env);
771     CHECK_ARG(env, object);
772     CHECK_ARG(env, result);
773 
774     auto napiVal = LocalValueFromJsValue(object);
775     RETURN_STATUS_IF_FALSE(env, napiVal->IsObject() || napiVal->IsFunction(), napi_object_expected);
776     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
777     auto obj = napiVal->ToObject(vm);
778     Local<panda::ArrayRef> arrayVal = obj->GetOwnPropertyNames(vm);
779     *result = JsValueFromLocalValue(arrayVal);
780     return napi_clear_last_error(env);
781 }
782 
napi_set_property(napi_env env,napi_value object,napi_value key,napi_value value)783 NAPI_EXTERN napi_status napi_set_property(napi_env env, napi_value object, napi_value key, napi_value value)
784 {
785     NAPI_PREAMBLE(env);
786     CHECK_ARG(env, object);
787     CHECK_ARG(env, key);
788     CHECK_ARG(env, value);
789 
790     auto nativeValue = LocalValueFromJsValue(object);
791     auto propKey = LocalValueFromJsValue(key);
792     auto propValue = LocalValueFromJsValue(value);
793     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
794     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
795     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
796     obj->Set(vm, propKey, propValue);
797 
798     return GET_RETURN_STATUS(env);
799 }
800 
napi_has_property(napi_env env,napi_value object,napi_value key,bool * result)801 NAPI_EXTERN napi_status napi_has_property(napi_env env, napi_value object, napi_value key, bool* result)
802 {
803     NAPI_PREAMBLE(env);
804     CHECK_ARG(env, object);
805     CHECK_ARG(env, key);
806     CHECK_ARG(env, result);
807 
808     auto nativeValue = LocalValueFromJsValue(object);
809     auto propKey = LocalValueFromJsValue(key);
810     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
811     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
812     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
813     *result = obj->Has(vm, propKey);
814 
815     return GET_RETURN_STATUS(env);
816 }
817 
napi_get_property(napi_env env,napi_value object,napi_value key,napi_value * result)818 NAPI_EXTERN napi_status napi_get_property(napi_env env, napi_value object, napi_value key, napi_value* result)
819 {
820     NAPI_PREAMBLE(env);
821     CHECK_ARG(env, object);
822     CHECK_ARG(env, key);
823     CHECK_ARG(env, result);
824 
825     auto nativeValue = LocalValueFromJsValue(object);
826     auto propKey = LocalValueFromJsValue(key);
827     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
828     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
829     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
830     Local<panda::JSValueRef> value = obj->Get(vm, propKey);
831     if (value->IsFunction()) {
832         FunctionSetContainerId(vm, value);
833     }
834     *result = JsValueFromLocalValue(value);
835 
836     return GET_RETURN_STATUS(env);
837 }
838 
napi_delete_property(napi_env env,napi_value object,napi_value key,bool * result)839 NAPI_EXTERN napi_status napi_delete_property(napi_env env, napi_value object, napi_value key, bool* result)
840 {
841     NAPI_PREAMBLE(env);
842     CHECK_ARG(env, object);
843     CHECK_ARG(env, key);
844 
845     auto nativeValue = LocalValueFromJsValue(object);
846     auto propKey = LocalValueFromJsValue(key);
847     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
848     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
849     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
850     bool deleteResult = obj->Delete(vm, propKey);
851     if (result) {
852         *result = deleteResult;
853     }
854 
855     return GET_RETURN_STATUS(env);
856 }
857 
napi_has_own_property(napi_env env,napi_value object,napi_value key,bool * result)858 NAPI_EXTERN napi_status napi_has_own_property(napi_env env, napi_value object, napi_value key, bool* result)
859 {
860     NAPI_PREAMBLE(env);
861     CHECK_ARG(env, object);
862     CHECK_ARG(env, key);
863     CHECK_ARG(env, result);
864 
865     auto nativeValue = LocalValueFromJsValue(object);
866     auto propKey = LocalValueFromJsValue(key);
867     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
868     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
869     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
870     bool hasResult = obj->Has(vm, propKey);
871     if (result) {
872         *result = hasResult;
873     }
874 
875     return GET_RETURN_STATUS(env);
876 }
877 
napi_set_named_property(napi_env env,napi_value object,const char * utf8name,napi_value value)878 NAPI_EXTERN napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, napi_value value)
879 {
880     NAPI_PREAMBLE(env);
881     CHECK_ARG(env, object);
882     CHECK_ARG(env, utf8name);
883     CHECK_ARG(env, value);
884 
885     auto nativeValue = LocalValueFromJsValue(object);
886     auto propKey = LocalValueFromJsValue(value);
887     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
888     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
889     Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, utf8name);
890     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
891     obj->Set(vm, key, propKey);
892 
893     return GET_RETURN_STATUS(env);
894 }
895 
napi_has_named_property(napi_env env,napi_value object,const char * utf8name,bool * result)896 NAPI_EXTERN napi_status napi_has_named_property(napi_env env, napi_value object, const char* utf8name, bool* result)
897 {
898     NAPI_PREAMBLE(env);
899     CHECK_ARG(env, object);
900     CHECK_ARG(env, utf8name);
901     CHECK_ARG(env, result);
902 
903     auto nativeValue = LocalValueFromJsValue(object);
904     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
905     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
906     Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, utf8name);
907     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
908     *result = obj->Has(vm, key);
909 
910     return GET_RETURN_STATUS(env);
911 }
912 
napi_get_named_property(napi_env env,napi_value object,const char * utf8name,napi_value * result)913 NAPI_EXTERN napi_status napi_get_named_property(napi_env env,
914                                                 napi_value object,
915                                                 const char* utf8name,
916                                                 napi_value* result)
917 {
918     NAPI_PREAMBLE(env);
919     CHECK_ARG(env, object);
920     CHECK_ARG(env, utf8name);
921     CHECK_ARG(env, result);
922 
923     auto nativeValue = LocalValueFromJsValue(object);
924     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
925     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
926     Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, utf8name);
927     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
928     Local<panda::JSValueRef> value = obj->Get(vm, key);
929     if (value->IsFunction()) {
930         FunctionSetContainerId(vm, value);
931     }
932     *result = JsValueFromLocalValue(value);
933 
934     return GET_RETURN_STATUS(env);
935 }
936 
napi_get_own_property_descriptor(napi_env env,napi_value object,const char * utf8name,napi_value * result)937 NAPI_EXTERN napi_status napi_get_own_property_descriptor(napi_env env,
938                                                          napi_value object,
939                                                          const char* utf8name,
940                                                          napi_value* result)
941 {
942     CHECK_ENV(env);
943     CHECK_ARG(env, object);
944     CHECK_ARG(env, utf8name);
945     CHECK_ARG(env, result);
946 
947     auto nativeValue = LocalValueFromJsValue(object);
948     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
949     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
950     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
951     Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, utf8name);
952     panda::PropertyAttribute property;
953     obj->GetOwnProperty(vm, key, property);
954     *result = JsValueFromLocalValue(property.GetValue(vm));
955     return napi_clear_last_error(env);
956 }
957 
napi_set_element(napi_env env,napi_value object,uint32_t index,napi_value value)958 NAPI_EXTERN napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value)
959 {
960     NAPI_PREAMBLE(env);
961     CHECK_ARG(env, object);
962     CHECK_ARG(env, value);
963 
964     auto nativeValue = LocalValueFromJsValue(object);
965     auto elementValue = LocalValueFromJsValue(value);
966     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
967     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
968     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
969     obj->Set(vm, index, elementValue);
970 
971     return GET_RETURN_STATUS(env);
972 }
973 
napi_has_element(napi_env env,napi_value object,uint32_t index,bool * result)974 NAPI_EXTERN napi_status napi_has_element(napi_env env, napi_value object, uint32_t index, bool* result)
975 {
976     NAPI_PREAMBLE(env);
977     CHECK_ARG(env, object);
978     CHECK_ARG(env, result);
979 
980     auto nativeValue = LocalValueFromJsValue(object);
981     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
982     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
983     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
984     *result = obj->Has(vm, index);
985 
986     return GET_RETURN_STATUS(env);
987 }
988 
napi_get_element(napi_env env,napi_value object,uint32_t index,napi_value * result)989 NAPI_EXTERN napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value* result)
990 {
991     NAPI_PREAMBLE(env);
992     CHECK_ARG(env, object);
993     CHECK_ARG(env, result);
994 
995     auto nativeValue = LocalValueFromJsValue(object);
996     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
997     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
998     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
999     Local<panda::JSValueRef> value = obj->Get(vm, index);
1000     if (value->IsFunction()) {
1001         FunctionSetContainerId(vm, value);
1002     }
1003     *result = JsValueFromLocalValue(value);
1004 
1005     return GET_RETURN_STATUS(env);
1006 }
1007 
napi_delete_element(napi_env env,napi_value object,uint32_t index,bool * result)1008 NAPI_EXTERN napi_status napi_delete_element(napi_env env, napi_value object, uint32_t index, bool* result)
1009 {
1010     NAPI_PREAMBLE(env);
1011     CHECK_ARG(env, object);
1012 
1013     auto nativeValue = LocalValueFromJsValue(object);
1014     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
1015     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1016     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
1017     bool deleteResult = obj->Delete(vm, index);
1018     if (result) {
1019         *result = deleteResult;
1020     }
1021 
1022     return GET_RETURN_STATUS(env);
1023 }
1024 
napi_define_properties(napi_env env,napi_value object,size_t property_count,const napi_property_descriptor * properties)1025 NAPI_EXTERN napi_status napi_define_properties(napi_env env,
1026                                                napi_value object,
1027                                                size_t property_count,
1028                                                const napi_property_descriptor* properties)
1029 {
1030     NAPI_PREAMBLE(env);
1031     CHECK_ARG(env, object);
1032     CHECK_ARG(env, properties);
1033 
1034     auto nativeValue = LocalValueFromJsValue(object);
1035     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(),
1036         napi_object_expected);
1037     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1038     Local<panda::ObjectRef> nativeObject = nativeValue->ToObject(vm);
1039 
1040     auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1041     for (size_t i = 0; i < property_count; i++) {
1042         if (nativeProperties[i].utf8name == nullptr) {
1043             auto name = LocalValueFromJsValue(nativeProperties[i].name);
1044             RETURN_STATUS_IF_FALSE(env, !name.IsEmpty() && (name->IsString() || name->IsSymbol()), napi_name_expected);
1045         }
1046         NapiDefineProperty(env, nativeObject, nativeProperties[i]);
1047     }
1048     return GET_RETURN_STATUS(env);
1049 }
1050 
1051 // Methods to work with Arrays
napi_is_array(napi_env env,napi_value value,bool * result)1052 NAPI_EXTERN napi_status napi_is_array(napi_env env, napi_value value, bool* result)
1053 {
1054     CHECK_ENV(env);
1055     CHECK_ARG(env, value);
1056     CHECK_ARG(env, result);
1057 
1058     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1059     auto nativeValue = LocalValueFromJsValue(value);
1060     *result = nativeValue->IsJSArray(vm);
1061     return napi_clear_last_error(env);
1062 }
1063 
napi_get_array_length(napi_env env,napi_value value,uint32_t * result)1064 NAPI_EXTERN napi_status napi_get_array_length(napi_env env, napi_value value, uint32_t* result)
1065 {
1066     NAPI_PREAMBLE(env);
1067     CHECK_ARG(env, value);
1068     CHECK_ARG(env, result);
1069 
1070     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1071     auto nativeValue = LocalValueFromJsValue(value);
1072     RETURN_STATUS_IF_FALSE(env, nativeValue->IsArray(vm), napi_array_expected);
1073     Local<panda::ArrayRef> arr(nativeValue);
1074     *result = arr->Length(vm);
1075 
1076     return GET_RETURN_STATUS(env);
1077 }
1078 
napi_is_sendable_object(napi_env env,napi_value value,bool * result)1079 NAPI_EXTERN napi_status napi_is_sendable_object(napi_env env, napi_value value, bool* result)
1080 {
1081     CHECK_ENV(env);
1082     CHECK_ARG(env, value);
1083     CHECK_ARG(env, result);
1084 
1085     auto nativeValue = LocalValueFromJsValue(value);
1086     *result = nativeValue->IsSharedObject();
1087     return napi_clear_last_error(env);
1088 }
1089 
1090 // Methods to compare values
napi_strict_equals(napi_env env,napi_value lhs,napi_value rhs,bool * result)1091 NAPI_EXTERN napi_status napi_strict_equals(napi_env env, napi_value lhs, napi_value rhs, bool* result)
1092 {
1093     CHECK_ENV(env);
1094     CHECK_ARG(env, lhs);
1095     CHECK_ARG(env, rhs);
1096     CHECK_ARG(env, result);
1097 
1098     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1099     auto nativeLhs = LocalValueFromJsValue(lhs);
1100     auto nativeRhs = LocalValueFromJsValue(rhs);
1101     *result = nativeLhs->IsStrictEquals(vm, nativeRhs);
1102     return napi_clear_last_error(env);
1103 }
1104 
1105 // 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)1106 NAPI_EXTERN napi_status napi_call_function(napi_env env,
1107                                            napi_value recv,
1108                                            napi_value func,
1109                                            size_t argc,
1110                                            const napi_value* argv,
1111                                            napi_value* result)
1112 {
1113     NAPI_PREAMBLE(env);
1114     CHECK_ARG(env, func);
1115     if (argc > 0) {
1116         CHECK_ARG(env, argv);
1117     }
1118 
1119     RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef *>(func)->IsFunction(), napi_function_expected);
1120     auto vm = reinterpret_cast<NativeEngine *>(env)->GetEcmaVm();
1121     panda::JSValueRef* thisObj = reinterpret_cast<panda::JSValueRef *>(recv);
1122     panda::FunctionRef* function = reinterpret_cast<panda::FunctionRef *>(func);
1123 #ifdef ENABLE_CONTAINER_SCOPE
1124     int32_t scopeId = OHOS::Ace::ContainerScope::CurrentId();
1125     auto funcInfo = reinterpret_cast<NapiFunctionInfo *>(function->GetData(vm));
1126     if (funcInfo != nullptr) {
1127         scopeId = funcInfo->scopeId;
1128     }
1129     OHOS::Ace::ContainerScope containerScope(scopeId);
1130 #endif
1131     panda::JSValueRef* value =
1132         function->CallForNapi(vm, thisObj, reinterpret_cast<panda::JSValueRef *const*>(argv), argc);
1133     if (tryCatch.HasCaught()) {
1134         HILOG_ERROR("pending exception when js function called, print exception info: ");
1135         panda::JSNApi::PrintExceptionInfo(vm);
1136         result = nullptr;
1137         return napi_set_last_error(env, napi_pending_exception);
1138     }
1139     if (result) {
1140         *result = reinterpret_cast<napi_value>(value);
1141     }
1142     return napi_clear_last_error(env);
1143 }
1144 
napi_new_instance(napi_env env,napi_value constructor,size_t argc,const napi_value * argv,napi_value * result)1145 NAPI_EXTERN napi_status napi_new_instance(napi_env env,
1146                                           napi_value constructor,
1147                                           size_t argc,
1148                                           const napi_value* argv,
1149                                           napi_value* result)
1150 {
1151     NAPI_PREAMBLE(env);
1152     CHECK_ARG(env, constructor);
1153     if (argc > 0) {
1154         CHECK_ARG(env, argv);
1155     }
1156     CHECK_ARG(env, result);
1157     RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef*>(constructor)->IsFunction(), napi_function_expected);
1158     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1159     panda::FunctionRef* constructorVal = reinterpret_cast<panda::FunctionRef*>(constructor);
1160     panda::JSValueRef* instance = constructorVal->ConstructorOptimize(vm,
1161         reinterpret_cast<panda::JSValueRef**>(const_cast<napi_value*>(argv)), argc);
1162     if (tryCatch.HasCaught()) {
1163         HILOG_ERROR("CreateInstance occur Exception");
1164         *result = nullptr;
1165     } else {
1166         *result = reinterpret_cast<napi_value>(instance);
1167     }
1168     return GET_RETURN_STATUS(env);
1169 }
1170 
napi_instanceof(napi_env env,napi_value object,napi_value constructor,bool * result)1171 NAPI_EXTERN napi_status napi_instanceof(napi_env env, napi_value object, napi_value constructor, bool* result)
1172 {
1173     NAPI_PREAMBLE(env);
1174     CHECK_ARG(env, object);
1175     CHECK_ARG(env, constructor);
1176     CHECK_ARG(env, result);
1177 
1178     auto nativeValue = LocalValueFromJsValue(object);
1179     auto nativeConstructor = LocalValueFromJsValue(constructor);
1180     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
1181     RETURN_STATUS_IF_FALSE(env, nativeConstructor->IsFunction(), napi_function_expected);
1182     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1183     *result = nativeValue->InstanceOf(vm, nativeConstructor);
1184 
1185     return GET_RETURN_STATUS(env);
1186 }
1187 
1188 // Methods to work with napi_callbacks
1189 // 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)1190 NAPI_EXTERN napi_status napi_get_cb_info(napi_env env,              // [in] NAPI environment handle
1191                                          napi_callback_info cbinfo, // [in] Opaque callback-info handle
1192                                          size_t* argc,         // [in-out] Specifies the size of the provided argv array
1193                                                                // and receives the actual count of args.
1194                                          napi_value* argv,     // [out] Array of values
1195                                          napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
1196                                          void** data)          // [out] Receives the data pointer for the callback.
1197 {
1198     CHECK_ENV(env);
1199     CHECK_ARG(env, cbinfo);
1200 
1201     auto info = reinterpret_cast<NapiNativeCallbackInfo*>(cbinfo);
1202     if ((argc != nullptr) && (argv != nullptr)) {
1203         size_t i = info->GetArgv(argv, *argc);
1204         if (i < *argc) {
1205             napi_value undefined = JsValueFromLocalValue(
1206                 panda::JSValueRef::Undefined(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm()));
1207             for (; i < *argc; i++) {
1208                 argv[i] = undefined;
1209             }
1210         }
1211     }
1212     if (argc != nullptr) {
1213         *argc = info->GetArgc();
1214     }
1215     if (this_arg != nullptr) {
1216         *this_arg = info->GetThisVar();
1217     }
1218     if (data != nullptr && info->GetFunctionInfo() != nullptr) {
1219         *data = info->GetFunctionInfo()->data;
1220     }
1221 
1222     return napi_clear_last_error(env);
1223 }
1224 
napi_get_new_target(napi_env env,napi_callback_info cbinfo,napi_value * result)1225 NAPI_EXTERN napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, napi_value* result)
1226 {
1227     NAPI_PREAMBLE(env);
1228     CHECK_ARG(env, cbinfo);
1229     CHECK_ARG(env, result);
1230 
1231     auto info = reinterpret_cast<NapiNativeCallbackInfo*>(cbinfo);
1232     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1233     auto thisVarObj = LocalValueFromJsValue(info->GetThisVar());
1234     auto functionVal = LocalValueFromJsValue(info->GetFunction());
1235     if (thisVarObj->InstanceOf(vm, functionVal)) {
1236         *result = info->GetFunction();
1237     } else {
1238         *result = nullptr;
1239     }
1240 
1241     return GET_RETURN_STATUS(env);
1242 }
1243 
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)1244 NAPI_EXTERN napi_status napi_define_class(napi_env env,
1245                                           const char* utf8name,
1246                                           size_t length,
1247                                           napi_callback constructor,
1248                                           void* data,
1249                                           size_t property_count,
1250                                           const napi_property_descriptor* properties,
1251                                           napi_value* result)
1252 {
1253     NAPI_PREAMBLE(env);
1254     CHECK_ARG(env, utf8name);
1255     RETURN_STATUS_IF_FALSE(env, length == NAPI_AUTO_LENGTH || length <= INT_MAX, napi_object_expected);
1256     CHECK_ARG(env, constructor);
1257     if (property_count > 0) {
1258         CHECK_ARG(env, properties);
1259     }
1260     CHECK_ARG(env, result);
1261 
1262     auto callback = reinterpret_cast<NapiNativeCallback>(constructor);
1263     auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1264 
1265     size_t nameLength = std::min(length, strlen(utf8name));
1266     char newName[nameLength + 1];
1267     if (strncpy_s(newName, nameLength + 1, utf8name, nameLength) != EOK) {
1268         HILOG_ERROR("napi_define_class strncpy_s failed");
1269         *result = nullptr;
1270     } else {
1271         EscapeLocalScope scope(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
1272         auto resultValue = NapiDefineClass(env, newName, callback, data, nativeProperties, property_count);
1273         *result = JsValueFromLocalValue(scope.Escape(resultValue));
1274     }
1275 
1276     return GET_RETURN_STATUS(env);
1277 }
1278 
1279 // 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)1280 NAPI_EXTERN napi_status napi_wrap(napi_env env,
1281                                   napi_value js_object,
1282                                   void* native_object,
1283                                   napi_finalize finalize_cb,
1284                                   void* finalize_hint,
1285                                   napi_ref* result)
1286 {
1287     NAPI_PREAMBLE(env);
1288     CHECK_ARG(env, js_object);
1289     CHECK_ARG(env, native_object);
1290     CHECK_ARG(env, finalize_cb);
1291 
1292     auto nativeValue = LocalValueFromJsValue(js_object);
1293     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1294     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
1295     auto engine = reinterpret_cast<NativeEngine*>(env);
1296     auto vm = engine->GetEcmaVm();
1297     auto nativeObject = nativeValue->ToObject(vm);
1298     size_t nativeBindingSize = 0;
1299     auto reference = reinterpret_cast<NativeReference**>(result);
1300     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1301     if (native_object == nullptr && nativeObject->Has(vm, key)) {
1302         Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1303         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(0));
1304         // Try to remove native pointer from ArrayDataList
1305         wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, nativeBindingSize);
1306         nativeObject->Delete(vm, key);
1307         delete ref;
1308     } else {
1309         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1310         NativeReference* ref = nullptr;
1311         if (reference != nullptr) {
1312             ref = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
1313             *reference = ref;
1314         } else {
1315             ref = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
1316         }
1317         object->SetNativePointerFieldCount(vm, 1);
1318         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize);
1319         PropertyAttribute attr(object, true, false, true);
1320         nativeObject->DefineProperty(vm, key, attr);
1321     }
1322     return GET_RETURN_STATUS(env);
1323 }
1324 
1325 // 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)1326 NAPI_EXTERN napi_status napi_wrap_with_size(napi_env env,
1327                                             napi_value js_object,
1328                                             void* native_object,
1329                                             napi_finalize finalize_cb,
1330                                             void* finalize_hint,
1331                                             napi_ref* result,
1332                                             size_t native_binding_size)
1333 {
1334     NAPI_PREAMBLE(env);
1335     CHECK_ARG(env, js_object);
1336     CHECK_ARG(env, native_object);
1337     CHECK_ARG(env, finalize_cb);
1338 
1339     auto nativeValue = LocalValueFromJsValue(js_object);
1340     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1341     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
1342     auto engine = reinterpret_cast<NativeEngine*>(env);
1343     auto vm = engine->GetEcmaVm();
1344     auto nativeObject = nativeValue->ToObject(vm);
1345     auto reference = reinterpret_cast<NativeReference**>(result);
1346     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1347     if (native_object == nullptr && nativeObject->Has(vm, key)) {
1348         Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1349         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(0));
1350         // Try to remove native pointer from ArrayDataList
1351         wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, native_binding_size);
1352         nativeObject->Delete(vm, key);
1353         delete ref;
1354     } else {
1355         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1356         NativeReference* ref = nullptr;
1357         if (reference != nullptr) {
1358             ref = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
1359             *reference = ref;
1360         } else {
1361             ref = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
1362         }
1363         object->SetNativePointerFieldCount(vm, 1);
1364         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, native_binding_size);
1365         PropertyAttribute attr(object, true, false, true);
1366         nativeObject->DefineProperty(vm, key, attr);
1367     }
1368 
1369     return GET_RETURN_STATUS(env);
1370 }
1371 
napi_unwrap(napi_env env,napi_value js_object,void ** result)1372 NAPI_EXTERN napi_status napi_unwrap(napi_env env, napi_value js_object, void** result)
1373 {
1374     NAPI_PREAMBLE(env);
1375     CHECK_ARG(env, js_object);
1376     CHECK_ARG(env, result);
1377 
1378     auto nativeValue = LocalValueFromJsValue(js_object);
1379     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
1380     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1381     auto nativeObject = nativeValue->ToObject(vm);
1382     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1383     Local<panda::JSValueRef> val = nativeObject->Get(vm, key);
1384     *result = nullptr;
1385     if (val->IsObject()) {
1386         Local<panda::ObjectRef> ext(val);
1387         auto ref = reinterpret_cast<NativeReference*>(ext->GetNativePointerField(0));
1388         *result = ref != nullptr ? ref->GetData() : nullptr;
1389     }
1390 
1391     return GET_RETURN_STATUS(env);
1392 }
1393 
napi_remove_wrap(napi_env env,napi_value js_object,void ** result)1394 NAPI_EXTERN napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result)
1395 {
1396     NAPI_PREAMBLE(env);
1397     CHECK_ARG(env, js_object);
1398     CHECK_ARG(env, result);
1399 
1400     auto nativeValue = LocalValueFromJsValue(js_object);
1401     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
1402     auto engine = reinterpret_cast<NativeEngine*>(env);
1403     auto vm = engine->GetEcmaVm();
1404     auto nativeObject = nativeValue->ToObject(vm);
1405     Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1406     Local<panda::JSValueRef> val = nativeObject->Get(vm, key);
1407     *result = nullptr;
1408     if (val->IsObject()) {
1409         Local<panda::ObjectRef> ext(val);
1410         auto ref = reinterpret_cast<NativeReference*>(ext->GetNativePointerField(0));
1411         *result = ref != nullptr ? ref->GetData() : nullptr;
1412     }
1413 
1414     size_t nativeBindingSize = 0;
1415     if (nativeObject->Has(vm, key)) {
1416         Local<panda::ObjectRef> wrapper = val;
1417         auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(0));
1418         // Try to remove native pointer from ArrayDataList
1419         wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, nativeBindingSize);
1420         nativeObject->Delete(vm, key);
1421         delete ref;
1422     } else {
1423         Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1424         NativeReference* ref = nullptr;
1425         ref = engine->CreateReference(js_object, 0, true, nullptr, nullptr, nullptr);
1426         object->SetNativePointerFieldCount(vm, 1);
1427         object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize);
1428         PropertyAttribute attr(object, true, false, true);
1429         nativeObject->DefineProperty(vm, key, attr);
1430     }
1431 
1432     return GET_RETURN_STATUS(env);
1433 }
1434 
napi_create_external(napi_env env,void * data,napi_finalize finalize_cb,void * finalize_hint,napi_value * result)1435 NAPI_EXTERN napi_status napi_create_external(
1436     napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint, napi_value* result)
1437 {
1438     NAPI_PREAMBLE(env);
1439     CHECK_ARG(env, result);
1440 
1441     auto engine = reinterpret_cast<NativeEngine*>(env);
1442     auto vm = engine->GetEcmaVm();
1443     auto callback = reinterpret_cast<NativeFinalize>(finalize_cb);
1444     NativeObjectInfo* info = NativeObjectInfo::CreateNewInstance();
1445     if (info == nullptr) {
1446         HILOG_ERROR("info is nullptr");
1447         return napi_set_last_error(env, napi_invalid_arg);
1448     }
1449     info->engine = engine;
1450     info->callback = callback;
1451     info->hint = finalize_hint;
1452     Local<panda::NativePointerRef> object = panda::NativePointerRef::New(vm, data,
1453         [](void* data, void* info) {
1454             auto externalInfo = reinterpret_cast<NativeObjectInfo*>(info);
1455             auto engine = externalInfo->engine;
1456             auto callback = externalInfo->callback;
1457             auto hint = externalInfo->hint;
1458             if (callback != nullptr) {
1459                 callback(engine, data, hint);
1460             }
1461             delete externalInfo;
1462         }, info, 0);
1463 
1464     *result = JsValueFromLocalValue(object);
1465     return napi_clear_last_error(env);
1466 }
1467 
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)1468 NAPI_EXTERN napi_status napi_create_external_with_size(napi_env env,
1469                                                        void* data,
1470                                                        napi_finalize finalize_cb,
1471                                                        void* finalize_hint,
1472                                                        napi_value* result,
1473                                                        size_t native_binding_size)
1474 {
1475     CHECK_ENV(env);
1476     CHECK_ARG(env, result);
1477 
1478     auto engine = reinterpret_cast<NativeEngine*>(env);
1479     auto vm = engine->GetEcmaVm();
1480     auto callback = reinterpret_cast<NativeFinalize>(finalize_cb);
1481     NativeObjectInfo* info = NativeObjectInfo::CreateNewInstance();
1482     if (info == nullptr) {
1483         HILOG_ERROR("info is nullptr");
1484         return napi_set_last_error(env, napi_function_expected);
1485     }
1486     info->engine = engine;
1487     info->nativeObject = nullptr;
1488     info->callback = callback;
1489     info->hint = finalize_hint;
1490     Local<panda::NativePointerRef> object = panda::NativePointerRef::New(vm, data,
1491         [](void* data, void* info) {
1492             auto externalInfo = reinterpret_cast<NativeObjectInfo*>(info);
1493             auto engine = externalInfo->engine;
1494             auto callback = externalInfo->callback;
1495             auto hint = externalInfo->hint;
1496             if (callback != nullptr) {
1497                 callback(engine, data, hint);
1498             }
1499             delete externalInfo;
1500         }, info, native_binding_size);
1501 
1502     *result = JsValueFromLocalValue(object);
1503     return napi_clear_last_error(env);
1504 }
1505 
napi_get_value_external(napi_env env,napi_value value,void ** result)1506 NAPI_EXTERN napi_status napi_get_value_external(napi_env env, napi_value value, void** result)
1507 {
1508     CHECK_ENV(env);
1509     CHECK_ARG(env, value);
1510     CHECK_ARG(env, result);
1511 
1512     auto nativeValue = LocalValueFromJsValue(value);
1513     RETURN_STATUS_IF_FALSE(env, nativeValue->IsNativePointer(), napi_object_expected);
1514     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1515     Local<panda::NativePointerRef> object = nativeValue->ToNativePointer(vm);
1516     *result = object->Value();
1517     return napi_clear_last_error(env);
1518 }
1519 
1520 // Methods to control object lifespan
1521 // 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)1522 NAPI_EXTERN napi_status napi_create_reference(napi_env env,
1523                                               napi_value value,
1524                                               uint32_t initial_refcount,
1525                                               napi_ref* result)
1526 {
1527     CHECK_ENV(env);
1528     CHECK_ARG(env, value);
1529     CHECK_ARG(env, result);
1530     auto engine = reinterpret_cast<ArkNativeEngine*>(env);
1531     auto ref = new ArkNativeReference(engine, engine->GetEcmaVm(), value, initial_refcount);
1532 
1533     *result = reinterpret_cast<napi_ref>(ref);
1534     return napi_clear_last_error(env);
1535 }
1536 
1537 // Deletes a reference. The referenced value is released, and may
1538 // be GC'd unless there are other references to it.
napi_delete_reference(napi_env env,napi_ref ref)1539 NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref)
1540 {
1541     CHECK_ENV(env);
1542     CHECK_ARG(env, ref);
1543 
1544     auto reference = reinterpret_cast<NativeReference*>(ref);
1545     uint32_t refCount = reference->GetRefCount();
1546     if (refCount > 0 || reference->GetFinalRun()) {
1547         delete reference;
1548         reference = nullptr;
1549     } else {
1550         reference->SetDeleteSelf();
1551     }
1552 
1553     return napi_clear_last_error(env);
1554 }
1555 
1556 // Increments the reference count, optionally returning the resulting count.
1557 // After this call the  reference will be a strong reference because its
1558 // refcount is >0, and the referenced object is effectively "pinned".
1559 // Calling this when the refcount is 0 and the object is unavailable
1560 // results in an error.
napi_reference_ref(napi_env env,napi_ref ref,uint32_t * result)1561 NAPI_EXTERN napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result)
1562 {
1563     CHECK_ENV(env);
1564     CHECK_ARG(env, ref);
1565 
1566     auto reference = reinterpret_cast<NativeReference*>(ref);
1567     uint32_t refCount = reference->Ref();
1568 
1569     if (result) {
1570         *result = refCount;
1571     }
1572 
1573     return napi_clear_last_error(env);
1574 }
1575 
1576 // Decrements the reference count, optionally returning the resulting count.
1577 // If the result is 0 the reference is now weak and the object may be GC'd
1578 // at any time if there are no other references. Calling this when the
1579 // refcount is already 0 results in an error.
napi_reference_unref(napi_env env,napi_ref ref,uint32_t * result)1580 NAPI_EXTERN napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result)
1581 {
1582     CHECK_ENV(env);
1583     CHECK_ARG(env, ref);
1584 
1585     auto reference = reinterpret_cast<NativeReference*>(ref);
1586     uint32_t unrefCount = reference->Unref();
1587 
1588     if (result) {
1589         *result = unrefCount;
1590     }
1591 
1592     return napi_clear_last_error(env);
1593 }
1594 
1595 // Attempts to get a referenced value. If the reference is weak,
1596 // the value might no longer be available, in that case the call
1597 // is still successful but the result is nullptr.
napi_get_reference_value(napi_env env,napi_ref ref,napi_value * result)1598 NAPI_EXTERN napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result)
1599 {
1600     CHECK_ENV(env);
1601     CHECK_ARG(env, ref);
1602     CHECK_ARG(env, result);
1603 
1604     auto reference = reinterpret_cast<NativeReference*>(ref);
1605 
1606     *result = reference->Get();
1607     return napi_clear_last_error(env);
1608 }
1609 
napi_open_handle_scope(napi_env env,napi_handle_scope * result)1610 NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result)
1611 {
1612     CHECK_ENV(env);
1613     CHECK_ARG(env, result);
1614 
1615     auto engine = reinterpret_cast<NativeEngine*>(env);
1616     *result = HandleScopeToNapiHandleScope(new HandleScopeWrapper(engine));
1617     engine->openHandleScopes_++;
1618     return napi_clear_last_error(env);
1619 }
1620 
napi_close_handle_scope(napi_env env,napi_handle_scope scope)1621 NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope)
1622 {
1623     CHECK_ENV(env);
1624     CHECK_ARG(env, scope);
1625 
1626     auto engine = reinterpret_cast<NativeEngine*>(env);
1627     if (engine->openHandleScopes_ == 0) {
1628         return napi_handle_scope_mismatch;
1629     }
1630 
1631     engine->openHandleScopes_--;
1632     delete NapiHandleScopeToHandleScope(scope);
1633     return napi_clear_last_error(env);
1634 }
1635 
napi_open_escapable_handle_scope(napi_env env,napi_escapable_handle_scope * result)1636 NAPI_EXTERN napi_status napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle_scope* result)
1637 {
1638     CHECK_ENV(env);
1639     CHECK_ARG(env, result);
1640 
1641     auto engine = reinterpret_cast<NativeEngine*>(env);
1642     *result = EscapableHandleScopeToNapiEscapableHandleScope(new EscapableHandleScopeWrapper(engine));
1643     engine->openHandleScopes_++;
1644     return napi_clear_last_error(env);
1645 }
1646 
napi_close_escapable_handle_scope(napi_env env,napi_escapable_handle_scope scope)1647 NAPI_EXTERN napi_status napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope scope)
1648 {
1649     CHECK_ENV(env);
1650     CHECK_ARG(env, scope);
1651 
1652     auto engine = reinterpret_cast<NativeEngine*>(env);
1653     if (engine->openHandleScopes_ == 0) {
1654         return napi_handle_scope_mismatch;
1655     }
1656 
1657     engine->openHandleScopes_--;
1658     delete NapiEscapableHandleScopeToEscapableHandleScope(scope);
1659     return napi_clear_last_error(env);
1660 }
1661 
napi_escape_handle(napi_env env,napi_escapable_handle_scope scope,napi_value escapee,napi_value * result)1662 NAPI_EXTERN napi_status napi_escape_handle(napi_env env,
1663                                            napi_escapable_handle_scope scope,
1664                                            napi_value escapee,
1665                                            napi_value* result)
1666 {
1667     CHECK_ENV(env);
1668     CHECK_ARG(env, scope);
1669     CHECK_ARG(env, escapee);
1670     CHECK_ARG(env, result);
1671 
1672     auto s = NapiEscapableHandleScopeToEscapableHandleScope(scope);
1673     if (!s->IsEscapeCalled()) {
1674         *result = JsValueFromLocalValue(s->Escape(LocalValueFromJsValue(escapee)));
1675         return napi_clear_last_error(env);
1676     }
1677     return napi_set_last_error(env, napi_escape_called_twice);
1678 }
1679 
1680 // Methods to support error handling
napi_throw(napi_env env,napi_value error)1681 NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error)
1682 {
1683     CHECK_ENV(env);
1684     CHECK_ARG(env, error);
1685 
1686     auto nativeValue = LocalValueFromJsValue(error);
1687     RETURN_STATUS_IF_FALSE(env, nativeValue->IsError(), napi_invalid_arg);
1688     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1689     panda::JSNApi::ThrowException(vm, nativeValue);
1690     return napi_clear_last_error(env);
1691 }
1692 
napi_throw_error(napi_env env,const char * code,const char * msg)1693 NAPI_EXTERN napi_status napi_throw_error(napi_env env, const char* code, const char* msg)
1694 {
1695     CHECK_ENV(env);
1696     CHECK_ARG(env, msg);
1697 
1698     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1699     Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
1700     error = panda::Exception::Error(vm, StringRef::NewFromUtf8(vm, msg));
1701     if (code != nullptr) {
1702         Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
1703         Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
1704         Local<panda::ObjectRef> errorObj(error);
1705         errorObj->Set(vm, codeKey, codeValue);
1706     }
1707     panda::JSNApi::ThrowException(vm, error);
1708     return napi_clear_last_error(env);
1709 }
1710 
napi_throw_type_error(napi_env env,const char * code,const char * msg)1711 NAPI_EXTERN napi_status napi_throw_type_error(napi_env env, const char* code, const char* msg)
1712 {
1713     CHECK_ENV(env);
1714     CHECK_ARG(env, msg);
1715 
1716     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1717     Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
1718     error = panda::Exception::TypeError(vm, StringRef::NewFromUtf8(vm, msg));
1719     if (code != nullptr) {
1720         Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
1721         Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
1722         Local<panda::ObjectRef> errorObj(error);
1723         errorObj->Set(vm, codeKey, codeValue);
1724     }
1725     panda::JSNApi::ThrowException(vm, error);
1726     return napi_clear_last_error(env);
1727 }
1728 
napi_throw_range_error(napi_env env,const char * code,const char * msg)1729 NAPI_EXTERN napi_status napi_throw_range_error(napi_env env, const char* code, const char* msg)
1730 {
1731     CHECK_ENV(env);
1732     CHECK_ARG(env, msg);
1733 
1734     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1735     Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
1736     error = panda::Exception::RangeError(vm, StringRef::NewFromUtf8(vm, msg));
1737     if (code != nullptr) {
1738         Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
1739         Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
1740         Local<panda::ObjectRef> errorObj(error);
1741         errorObj->Set(vm, codeKey, codeValue);
1742     }
1743     panda::JSNApi::ThrowException(vm, error);
1744     return napi_clear_last_error(env);
1745 }
1746 
napi_is_error(napi_env env,napi_value value,bool * result)1747 NAPI_EXTERN napi_status napi_is_error(napi_env env, napi_value value, bool* result)
1748 {
1749     CHECK_ENV(env);
1750     CHECK_ARG(env, value);
1751     CHECK_ARG(env, result);
1752 
1753     auto nativeValue = LocalValueFromJsValue(value);
1754     *result = nativeValue->IsError();
1755 
1756     return napi_clear_last_error(env);
1757 }
1758 
1759 // Methods to support catching exceptions
napi_is_exception_pending(napi_env env,bool * result)1760 NAPI_EXTERN napi_status napi_is_exception_pending(napi_env env, bool* result)
1761 {
1762     CHECK_ENV(env);
1763     CHECK_ARG(env, result);
1764 
1765     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1766     *result = panda::JSNApi::HasPendingException(vm);
1767     return napi_clear_last_error(env);
1768 }
1769 
napi_get_and_clear_last_exception(napi_env env,napi_value * result)1770 NAPI_EXTERN napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result)
1771 {
1772     CHECK_ENV(env);
1773     CHECK_ARG(env, result);
1774 
1775     auto engine = reinterpret_cast<NativeEngine*>(env);
1776     auto vm = engine->GetEcmaVm();
1777     engine->lastException_.Empty();
1778     Local<panda::ObjectRef> exception = panda::JSNApi::GetAndClearUncaughtException(vm);
1779     if (!exception.IsNull()) {
1780         *result = JsValueFromLocalValue(exception);
1781     }
1782 
1783     return napi_clear_last_error(env);
1784 }
1785 
1786 // Methods to work with array buffers and typed arrays
napi_is_arraybuffer(napi_env env,napi_value value,bool * result)1787 NAPI_EXTERN napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result)
1788 {
1789     CHECK_ENV(env);
1790     CHECK_ARG(env, value);
1791     CHECK_ARG(env, result);
1792 
1793     auto nativeValue = LocalValueFromJsValue(value);
1794     *result = nativeValue->IsArrayBuffer();
1795 
1796     return napi_clear_last_error(env);
1797 }
1798 
napi_create_arraybuffer(napi_env env,size_t byte_length,void ** data,napi_value * result)1799 NAPI_EXTERN napi_status napi_create_arraybuffer(napi_env env, size_t byte_length, void** data, napi_value* result)
1800 {
1801     NAPI_PREAMBLE(env);
1802     CHECK_ARG(env, data);
1803     CHECK_ARG(env, result);
1804 
1805     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1806     uint8_t** values = (uint8_t**)(data);
1807     Local<panda::ArrayBufferRef> res = panda::ArrayBufferRef::New(vm, byte_length);
1808     if (values != nullptr) {
1809         *values = reinterpret_cast<uint8_t*>(res->GetBuffer());
1810     }
1811     *result = JsValueFromLocalValue(res);
1812 
1813     return GET_RETURN_STATUS(env);
1814 }
1815 
napi_create_external_arraybuffer(napi_env env,void * external_data,size_t byte_length,napi_finalize finalize_cb,void * finalize_hint,napi_value * result)1816 NAPI_EXTERN napi_status napi_create_external_arraybuffer(napi_env env,
1817                                                          void* external_data,
1818                                                          size_t byte_length,
1819                                                          napi_finalize finalize_cb,
1820                                                          void* finalize_hint,
1821                                                          napi_value* result)
1822 {
1823     NAPI_PREAMBLE(env);
1824     CHECK_ARG(env, external_data);
1825     CHECK_ARG(env, finalize_cb);
1826     CHECK_ARG(env, result);
1827 
1828     auto engine = reinterpret_cast<NativeEngine*>(env);
1829     auto vm = engine->GetEcmaVm();
1830     auto callback = reinterpret_cast<NativeFinalize>(finalize_cb);
1831     uint8_t* value = (uint8_t*)external_data;
1832     NativeObjectInfo* cbinfo = NativeObjectInfo::CreateNewInstance();
1833     if (cbinfo == nullptr) {
1834         HILOG_ERROR("cbinfo is nullptr");
1835         return napi_set_last_error(env, napi_function_expected);
1836     }
1837     cbinfo->engine = engine;
1838     cbinfo->callback = callback;
1839     cbinfo->hint = finalize_hint;
1840 
1841     Local<panda::ArrayBufferRef> object = panda::ArrayBufferRef::New(vm, value, byte_length,
1842         [](void* data, void* info) {
1843             auto externalInfo = reinterpret_cast<NativeObjectInfo*>(info);
1844             auto engine = externalInfo->engine;
1845             auto callback = externalInfo->callback;
1846             auto hint = externalInfo->hint;
1847             if (callback != nullptr) {
1848                 callback(engine, data, hint);
1849             }
1850             delete externalInfo;
1851         },
1852         cbinfo);
1853     *result = JsValueFromLocalValue(object);
1854     return GET_RETURN_STATUS(env);
1855 }
1856 
napi_get_arraybuffer_info(napi_env env,napi_value arraybuffer,void ** data,size_t * byte_length)1857 NAPI_EXTERN napi_status napi_get_arraybuffer_info(napi_env env,
1858                                                   napi_value arraybuffer,
1859                                                   void** data,
1860                                                   size_t* byte_length)
1861 {
1862     CHECK_ENV(env);
1863     CHECK_ARG(env, arraybuffer);
1864     CHECK_ARG(env, data);
1865     CHECK_ARG(env, byte_length);
1866 
1867     auto nativeValue = LocalValueFromJsValue(arraybuffer);
1868     RETURN_STATUS_IF_FALSE(env, nativeValue->IsArrayBuffer(), napi_status::napi_arraybuffer_expected);
1869     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1870     Local<panda::ArrayBufferRef> res = nativeValue->ToObject(vm);
1871     *data = res->GetBuffer();
1872     *byte_length = res->ByteLength(vm);
1873 
1874     return napi_clear_last_error(env);
1875 }
1876 
napi_is_typedarray(napi_env env,napi_value value,bool * result)1877 NAPI_EXTERN napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result)
1878 {
1879     CHECK_ENV(env);
1880     CHECK_ARG(env, value);
1881 
1882     auto nativeValue = LocalValueFromJsValue(value);
1883     *result = nativeValue->IsTypedArray();
1884 
1885     return napi_clear_last_error(env);
1886 }
1887 
1888 EXTERN_C_START
napi_is_buffer(napi_env env,napi_value value,bool * result)1889 NAPI_EXTERN napi_status napi_is_buffer(napi_env env, napi_value value, bool* result)
1890 {
1891     CHECK_ENV(env);
1892     CHECK_ARG(env, value);
1893     CHECK_ARG(env, result);
1894 
1895     auto nativeValue = LocalValueFromJsValue(value);
1896     *result = nativeValue->IsBuffer();
1897 
1898     return napi_clear_last_error(env);
1899 }
1900 
napi_create_buffer(napi_env env,size_t size,void ** data,napi_value * result)1901 NAPI_EXTERN napi_status napi_create_buffer(napi_env env, size_t size, void** data, napi_value* result)
1902 {
1903     CHECK_ENV(env);
1904     CHECK_ARG(env, data);
1905     CHECK_ARG(env, result);
1906     RETURN_STATUS_IF_FALSE(env, size > 0, napi_invalid_arg);
1907 
1908     uint8_t** value =  reinterpret_cast<uint8_t**>(data);
1909     if (!value) {
1910         HILOG_ERROR("value is empty");
1911         return napi_set_last_error(env, napi_invalid_arg);
1912     }
1913 
1914     if (size > MAX_BYTE_LENGTH) {
1915         HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
1916                     static_cast<float>(size) / static_cast<float>(ONEMIB_BYTE_SIZE),
1917                     static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
1918         *value = nullptr;
1919         return napi_set_last_error(env, napi_invalid_arg);
1920     }
1921     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1922     Local<panda::BufferRef> obj = BufferRef::New(vm, size);
1923     *value = reinterpret_cast<uint8_t*>(obj->GetBuffer());
1924 
1925     CHECK_ARG(env, *data);
1926     void* ptr = obj->GetBuffer();
1927     CHECK_ARG(env, ptr);
1928 
1929     *result = JsValueFromLocalValue(obj);
1930     return napi_clear_last_error(env);
1931 }
1932 
napi_create_buffer_copy(napi_env env,size_t length,const void * data,void ** result_data,napi_value * result)1933 NAPI_EXTERN napi_status napi_create_buffer_copy(napi_env env,
1934                                                 size_t length,
1935                                                 const void* data,
1936                                                 void** result_data,
1937                                                 napi_value* result)
1938 {
1939     CHECK_ENV(env);
1940     CHECK_ARG(env, data);
1941     CHECK_ARG(env, result_data);
1942     CHECK_ARG(env, result);
1943     RETURN_STATUS_IF_FALSE(env, length > 0, napi_invalid_arg);
1944 
1945     uint8_t** value = reinterpret_cast<uint8_t**>(result_data);
1946     const uint8_t* recvdata = (uint8_t*)data;
1947     if (!value) {
1948         HILOG_ERROR("value is empty");
1949         return napi_set_last_error(env, napi_invalid_arg);
1950     }
1951     if (length > MAX_BYTE_LENGTH) {
1952         HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
1953                     static_cast<float>(length) / static_cast<float>(ONEMIB_BYTE_SIZE),
1954                     static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
1955         *value = nullptr;
1956         return napi_set_last_error(env, napi_invalid_arg);
1957     }
1958     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1959     Local<panda::BufferRef> obj = BufferRef::New(vm, length);
1960     if (obj->IsUndefined()) {
1961         HILOG_INFO("engine create buffer_copy failed!");
1962     }
1963     *value = reinterpret_cast<uint8_t*>(obj->GetBuffer());
1964     if (memcpy_s(*value, length, recvdata, length) != EOK) {
1965         HILOG_ERROR("memcpy_s failed");
1966     }
1967 
1968     void* ptr = obj->GetBuffer();
1969     CHECK_ARG(env, ptr);
1970 
1971     *result = JsValueFromLocalValue(obj);
1972     return napi_clear_last_error(env);
1973 }
1974 
napi_create_external_buffer(napi_env env,size_t length,void * data,napi_finalize finalize_cb,void * finalize_hint,napi_value * result)1975 NAPI_EXTERN napi_status napi_create_external_buffer(napi_env env,
1976                                                     size_t length,
1977                                                     void* data,
1978                                                     napi_finalize finalize_cb,
1979                                                     void* finalize_hint,
1980                                                     napi_value* result)
1981 {
1982     NAPI_PREAMBLE(env);
1983     CHECK_ARG(env, result);
1984     CHECK_ARG(env, data);
1985     RETURN_STATUS_IF_FALSE(env, length > 0, napi_invalid_arg);
1986 
1987     auto callback = reinterpret_cast<NativeFinalize>(finalize_cb);
1988     uint8_t* value = (uint8_t*)data;
1989     if (!value) {
1990         HILOG_ERROR("value is empty");
1991         return napi_set_last_error(env, napi_invalid_arg);
1992     }
1993     if (length > MAX_BYTE_LENGTH) {
1994         HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
1995                     static_cast<float>(length) / static_cast<float>(ONEMIB_BYTE_SIZE),
1996                     static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
1997         value = nullptr;
1998         return napi_set_last_error(env, napi_invalid_arg);
1999     }
2000 
2001     auto engine = reinterpret_cast<NativeEngine*>(env);
2002     auto vm = engine->GetEcmaVm();
2003     std::unique_ptr<NativeObjectInfo> cbinfo(NativeObjectInfo::CreateNewInstance());
2004     if (!cbinfo) {
2005         HILOG_ERROR("cbinfo is nullptr");
2006         return napi_set_last_error(env, napi_function_expected);
2007     }
2008     cbinfo->engine = engine;
2009     cbinfo->callback = callback;
2010     cbinfo->hint = finalize_hint;
2011 
2012     Local<panda::BufferRef> object = panda::BufferRef::New(vm, value, length,
2013         [](void* data, void* info) {
2014             auto externalInfo = reinterpret_cast<NativeObjectInfo*>(info);
2015             auto engine = externalInfo->engine;
2016             auto callback = externalInfo->callback;
2017             auto hint = externalInfo->hint;
2018             if (callback != nullptr) {
2019                 callback(engine, data, hint);
2020             }
2021             delete externalInfo;
2022         },
2023         cbinfo.get());
2024     cbinfo.release();
2025     void* ptr = object->GetBuffer();
2026     CHECK_ARG(env, ptr);
2027 
2028     *result = JsValueFromLocalValue(object);
2029     return GET_RETURN_STATUS(env);
2030 }
2031 
napi_get_buffer_info(napi_env env,napi_value value,void ** data,size_t * length)2032 NAPI_EXTERN napi_status napi_get_buffer_info(napi_env env, napi_value value, void** data, size_t* length)
2033 {
2034     CHECK_ENV(env);
2035     CHECK_ARG(env, value);
2036 
2037     auto nativeValue = LocalValueFromJsValue(value);
2038     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBuffer(), napi_status::napi_arraybuffer_expected);
2039     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2040     Local<panda::BufferRef> res = nativeValue->ToObject(vm);
2041     *data = res->GetBuffer();
2042     *length = res->ByteLength(vm);
2043 
2044     return napi_clear_last_error(env);
2045 }
2046 
napi_object_freeze(napi_env env,napi_value object)2047 NAPI_EXTERN napi_status napi_object_freeze(napi_env env, napi_value object)
2048 {
2049     NAPI_PREAMBLE(env);
2050     CHECK_ARG(env, object);
2051 
2052     auto nativeValue = LocalValueFromJsValue(object);
2053     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
2054     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2055     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
2056     obj->Freeze(vm);
2057 
2058     return GET_RETURN_STATUS(env);
2059 }
2060 
napi_object_seal(napi_env env,napi_value object)2061 NAPI_EXTERN napi_status napi_object_seal(napi_env env, napi_value object)
2062 {
2063     NAPI_PREAMBLE(env);
2064     CHECK_ARG(env, object);
2065 
2066     auto nativeValue = LocalValueFromJsValue(object);
2067     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
2068     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2069     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
2070     obj->Seal(vm);
2071 
2072     return GET_RETURN_STATUS(env);
2073 }
2074 
2075 EXTERN_C_END
2076 
napi_create_typedarray(napi_env env,napi_typedarray_type type,size_t length,napi_value arraybuffer,size_t byte_offset,napi_value * result)2077 NAPI_EXTERN napi_status napi_create_typedarray(napi_env env,
2078                                                napi_typedarray_type type,
2079                                                size_t length,
2080                                                napi_value arraybuffer,
2081                                                size_t byte_offset,
2082                                                napi_value* result)
2083 {
2084     NAPI_PREAMBLE(env);
2085     CHECK_ARG(env, arraybuffer);
2086     CHECK_ARG(env, result);
2087 
2088     auto value = LocalValueFromJsValue(arraybuffer);
2089     auto typedArrayType = (NativeTypedArrayType)type;
2090     RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_status::napi_arraybuffer_expected);
2091     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2092     Local<panda::ArrayBufferRef> arrayBuf = value->ToObject(vm);
2093     Local<panda::TypedArrayRef> typedArray(panda::JSValueRef::Undefined(vm));
2094 
2095     switch (typedArrayType) {
2096         case NATIVE_INT8_ARRAY:
2097             typedArray = panda::Int8ArrayRef::New(vm, arrayBuf, byte_offset, length);
2098             break;
2099         case NATIVE_UINT8_ARRAY:
2100             typedArray = panda::Uint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
2101             break;
2102         case NATIVE_UINT8_CLAMPED_ARRAY:
2103             typedArray = panda::Uint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
2104             break;
2105         case NATIVE_INT16_ARRAY:
2106             typedArray = panda::Int16ArrayRef::New(vm, arrayBuf, byte_offset, length);
2107             break;
2108         case NATIVE_UINT16_ARRAY:
2109             typedArray = panda::Uint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
2110             break;
2111         case NATIVE_INT32_ARRAY:
2112             typedArray = panda::Int32ArrayRef::New(vm, arrayBuf, byte_offset, length);
2113             break;
2114         case NATIVE_UINT32_ARRAY:
2115             typedArray = panda::Uint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
2116             break;
2117         case NATIVE_FLOAT32_ARRAY:
2118             typedArray = panda::Float32ArrayRef::New(vm, arrayBuf, byte_offset, length);
2119             break;
2120         case NATIVE_FLOAT64_ARRAY:
2121             typedArray = panda::Float64ArrayRef::New(vm, arrayBuf, byte_offset, length);
2122             break;
2123         case NATIVE_BIGINT64_ARRAY:
2124             typedArray = panda::BigInt64ArrayRef::New(vm, arrayBuf, byte_offset, length);
2125             break;
2126         case NATIVE_BIGUINT64_ARRAY:
2127             typedArray = panda::BigUint64ArrayRef::New(vm, arrayBuf, byte_offset, length);
2128             break;
2129         default:
2130             *result = nullptr;
2131             return napi_set_last_error(env, napi_invalid_arg);
2132     }
2133     *result = JsValueFromLocalValue(typedArray);
2134     return GET_RETURN_STATUS(env);
2135 }
2136 
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)2137 NAPI_EXTERN napi_status napi_get_typedarray_info(napi_env env,
2138                                                  napi_value typedarray,
2139                                                  napi_typedarray_type* type,
2140                                                  size_t* length,
2141                                                  void** data,
2142                                                  napi_value* arraybuffer,
2143                                                  size_t* byte_offset)
2144 {
2145     CHECK_ENV(env);
2146     CHECK_ARG(env, typedarray);
2147 
2148     auto value = LocalValueFromJsValue(typedarray);
2149     RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_status::napi_invalid_arg);
2150     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2151     Local<panda::TypedArrayRef> typedArray = value->ToObject(vm);
2152     if (type != nullptr) {
2153         NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
2154         if (typedArray->IsInt8Array()) {
2155             thisType = NATIVE_INT8_ARRAY;
2156         } else if (typedArray->IsUint8Array()) {
2157             thisType = NATIVE_UINT8_ARRAY;
2158         } else if (typedArray->IsUint8ClampedArray()) {
2159             thisType = NATIVE_UINT8_CLAMPED_ARRAY;
2160         } else if (typedArray->IsInt16Array()) {
2161             thisType = NATIVE_INT16_ARRAY;
2162         } else if (typedArray->IsUint16Array()) {
2163             thisType = NATIVE_UINT16_ARRAY;
2164         } else if (typedArray->IsInt32Array()) {
2165             thisType = NATIVE_INT32_ARRAY;
2166         } else if (typedArray->IsUint32Array()) {
2167             thisType = NATIVE_UINT32_ARRAY;
2168         } else if (typedArray->IsFloat32Array()) {
2169             thisType = NATIVE_FLOAT32_ARRAY;
2170         } else if (typedArray->IsFloat64Array()) {
2171             thisType = NATIVE_FLOAT64_ARRAY;
2172         } else if (typedArray->IsBigInt64Array()) {
2173             thisType = NATIVE_BIGINT64_ARRAY;
2174         } else if (typedArray->IsBigUint64Array()) {
2175             thisType = NATIVE_BIGUINT64_ARRAY;
2176         }
2177         *type = (napi_typedarray_type)(thisType);
2178     }
2179     if (length != nullptr) {
2180         *length = typedArray->ByteLength(vm);
2181     }
2182     if (data != nullptr) {
2183         *data = static_cast<uint8_t*>(typedArray->GetArrayBuffer(vm)->GetBuffer()) + typedArray->ByteOffset(vm);
2184     }
2185     if (arraybuffer != nullptr) {
2186         *arraybuffer = JsValueFromLocalValue(typedArray->GetArrayBuffer(vm));
2187     }
2188     if (byte_offset != nullptr) {
2189         *byte_offset = typedArray->ByteOffset(vm);
2190     }
2191 
2192     return napi_clear_last_error(env);
2193 }
2194 
napi_create_dataview(napi_env env,size_t length,napi_value arraybuffer,size_t byte_offset,napi_value * result)2195 NAPI_EXTERN napi_status napi_create_dataview(napi_env env,
2196                                              size_t length,
2197                                              napi_value arraybuffer,
2198                                              size_t byte_offset,
2199                                              napi_value* result)
2200 {
2201     NAPI_PREAMBLE(env);
2202     CHECK_ARG(env, arraybuffer);
2203     CHECK_ARG(env, result);
2204 
2205     auto arrayBufferValue = LocalValueFromJsValue(arraybuffer);
2206     RETURN_STATUS_IF_FALSE(env, arrayBufferValue->IsArrayBuffer(), napi_status::napi_arraybuffer_expected);
2207     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2208     Local<panda::ArrayBufferRef> res = arrayBufferValue->ToObject(vm);
2209     if (length + byte_offset > static_cast<size_t>(res->ByteLength(vm))) {
2210         napi_throw_range_error(
2211             env,
2212             "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2213             "byte_offset + byte_length should be less than or "
2214             "equal to the size in bytes of the array passed in");
2215         return napi_set_last_error(env, napi_pending_exception);
2216     }
2217 
2218     Local<panda::DataViewRef> dataView = panda::DataViewRef::New(vm, res, byte_offset, length);
2219     *result = JsValueFromLocalValue(dataView);
2220     return GET_RETURN_STATUS(env);
2221 }
2222 
napi_is_dataview(napi_env env,napi_value value,bool * result)2223 NAPI_EXTERN napi_status napi_is_dataview(napi_env env, napi_value value, bool* result)
2224 {
2225     CHECK_ENV(env);
2226     CHECK_ARG(env, value);
2227     CHECK_ARG(env, result);
2228 
2229     auto nativeValue = LocalValueFromJsValue(value);
2230     *result = nativeValue->IsDataView();
2231 
2232     return napi_clear_last_error(env);
2233 }
2234 
napi_get_dataview_info(napi_env env,napi_value dataview,size_t * bytelength,void ** data,napi_value * arraybuffer,size_t * byte_offset)2235 NAPI_EXTERN napi_status napi_get_dataview_info(napi_env env,
2236                                                napi_value dataview,
2237                                                size_t* bytelength,
2238                                                void** data,
2239                                                napi_value* arraybuffer,
2240                                                size_t* byte_offset)
2241 {
2242     CHECK_ENV(env);
2243     CHECK_ARG(env, dataview);
2244 
2245     auto nativeValue = LocalValueFromJsValue(dataview);
2246     RETURN_STATUS_IF_FALSE(env, nativeValue->IsDataView(), napi_status::napi_invalid_arg);
2247     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2248     Local<panda::DataViewRef> dataViewObj = nativeValue->ToObject(vm);
2249     if (bytelength != nullptr) {
2250         *bytelength = dataViewObj->ByteLength();
2251     }
2252     if (data != nullptr) {
2253         *data = dataViewObj->GetArrayBuffer(vm)->GetBuffer();
2254     }
2255     if (arraybuffer != nullptr) {
2256         *arraybuffer = JsValueFromLocalValue(dataViewObj->GetArrayBuffer(vm));
2257     }
2258     if (byte_offset != nullptr) {
2259         *byte_offset = dataViewObj->ByteOffset();
2260     }
2261 
2262     return napi_clear_last_error(env);
2263 }
2264 
2265 // version management
napi_get_version(napi_env env,uint32_t * result)2266 NAPI_EXTERN napi_status napi_get_version(napi_env env, uint32_t* result)
2267 {
2268     CHECK_ENV(env);
2269     CHECK_ARG(env, result);
2270 
2271     *result = NAPI_VERSION;
2272     return napi_clear_last_error(env);
2273 }
2274 
2275 // Promises
napi_create_promise(napi_env env,napi_deferred * deferred,napi_value * promise)2276 NAPI_EXTERN napi_status napi_create_promise(napi_env env, napi_deferred* deferred, napi_value* promise)
2277 {
2278     NAPI_PREAMBLE(env);
2279     CHECK_ARG(env, deferred);
2280     CHECK_ARG(env, promise);
2281 
2282     auto engine = reinterpret_cast<NativeEngine*>(env);
2283     auto resultValue = engine->CreatePromise(reinterpret_cast<NativeDeferred**>(deferred));
2284     *promise = resultValue;
2285 
2286     return GET_RETURN_STATUS(env);
2287 }
2288 
napi_resolve_deferred(napi_env env,napi_deferred deferred,napi_value resolution)2289 NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution)
2290 {
2291     NAPI_PREAMBLE(env);
2292     CHECK_ARG(env, deferred);
2293     CHECK_ARG(env, resolution);
2294 
2295     auto nativeDeferred = reinterpret_cast<NativeDeferred*>(deferred);
2296     nativeDeferred->Resolve(resolution);
2297     delete nativeDeferred;
2298     return GET_RETURN_STATUS(env);
2299 }
2300 
napi_reject_deferred(napi_env env,napi_deferred deferred,napi_value rejection)2301 NAPI_EXTERN napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection)
2302 {
2303     NAPI_PREAMBLE(env);
2304     CHECK_ARG(env, deferred);
2305     CHECK_ARG(env, rejection);
2306 
2307     auto nativeDeferred = reinterpret_cast<NativeDeferred*>(deferred);
2308     nativeDeferred->Reject(rejection);
2309     delete nativeDeferred;
2310     return GET_RETURN_STATUS(env);
2311 }
2312 
napi_is_promise(napi_env env,napi_value value,bool * is_promise)2313 NAPI_EXTERN napi_status napi_is_promise(napi_env env, napi_value value, bool* is_promise)
2314 {
2315     CHECK_ENV(env);
2316     CHECK_ARG(env, value);
2317     CHECK_ARG(env, is_promise);
2318 
2319     auto nativeValue = LocalValueFromJsValue(value);
2320     *is_promise = nativeValue->IsPromise();
2321 
2322     return napi_clear_last_error(env);
2323 }
2324 
2325 // promise reject events
napi_set_promise_rejection_callback(napi_env env,napi_ref ref,napi_ref checkRef)2326 NAPI_EXTERN napi_status napi_set_promise_rejection_callback(napi_env env, napi_ref ref, napi_ref checkRef)
2327 {
2328     CHECK_ENV(env);
2329     CHECK_ARG(env, ref);
2330     CHECK_ARG(env, checkRef);
2331 
2332     auto rejectCallbackRef = reinterpret_cast<NativeReference*>(ref);
2333     auto checkCallbackRef = reinterpret_cast<NativeReference*>(checkRef);
2334     if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
2335         HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
2336     } else {
2337         auto engine = reinterpret_cast<NativeEngine*>(env);
2338         auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
2339         engine->SetPromiseRejectCallBackRef(rejectCallbackRef);
2340         engine->SetCheckCallbackRef(checkCallbackRef);
2341         panda::JSNApi::SetHostPromiseRejectionTracker(const_cast<EcmaVM*>(vm), engine->GetPromiseRejectCallback(),
2342                                                       reinterpret_cast<void*>(engine));
2343     }
2344 
2345     return napi_clear_last_error(env);
2346 }
2347 
2348 // Running a script
napi_run_script(napi_env env,napi_value script,napi_value * result)2349 NAPI_EXTERN napi_status napi_run_script(napi_env env, napi_value script, napi_value* result)
2350 {
2351     CHECK_ENV(env);
2352     CHECK_ARG(env, script);
2353     CHECK_ARG(env, result);
2354 
2355     *result = nullptr;
2356     return napi_clear_last_error(env);
2357 }
2358 
2359 // Runnint a buffer script, only used in ark
napi_run_buffer_script(napi_env env,std::vector<uint8_t> & buffer,napi_value * result)2360 NAPI_EXTERN napi_status napi_run_buffer_script(napi_env env, std::vector<uint8_t>& buffer, napi_value* result)
2361 {
2362     NAPI_PREAMBLE(env);
2363     CHECK_ARG(env, result);
2364 
2365     auto engine = reinterpret_cast<NativeEngine*>(env);
2366     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
2367     [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION);
2368     if (panda::JSNApi::HasPendingException(vm)) {
2369         if (engine->GetNapiUncaughtExceptionCallback() != nullptr) {
2370             LocalScope scope(vm);
2371             Local<ObjectRef> exception = panda::JSNApi::GetAndClearUncaughtException(vm);
2372             auto value = JsValueFromLocalValue(exception);
2373             if (!exception.IsEmpty() && !exception->IsHole()) {
2374                 engine->GetNapiUncaughtExceptionCallback()(value);
2375             }
2376         }
2377         *result = nullptr;
2378     }
2379 
2380     Local<PrimitiveRef> value = panda::JSValueRef::Undefined(vm);
2381     *result = JsValueFromLocalValue(value);
2382     return GET_RETURN_STATUS(env);
2383 }
2384 
napi_run_actor(napi_env env,std::vector<uint8_t> & buffer,const char * descriptor,napi_value * result,char * entryPoint)2385 NAPI_EXTERN napi_status napi_run_actor(napi_env env,
2386                                        std::vector<uint8_t>& buffer,
2387                                        const char* descriptor,
2388                                        napi_value* result,
2389                                        char* entryPoint)
2390 {
2391     NAPI_PREAMBLE(env);
2392     CHECK_ARG(env, result);
2393 
2394     auto engine = reinterpret_cast<NativeEngine*>(env);
2395     *result = engine->RunActor(buffer, descriptor, entryPoint);
2396     return GET_RETURN_STATUS(env);
2397 }
2398 
napi_load_module(napi_env env,const char * path,napi_value * result)2399 NAPI_EXTERN napi_status napi_load_module(napi_env env, const char* path, napi_value* result)
2400 {
2401     CHECK_ENV(env);
2402     CHECK_ARG(env, result);
2403 
2404     auto engine = reinterpret_cast<NativeEngine*>(env);
2405     *result = engine->NapiLoadModule(path);
2406     return napi_clear_last_error(env);
2407 }
2408 
2409 // Memory management
napi_adjust_external_memory(napi_env env,int64_t change_in_bytes,int64_t * adjusted_value)2410 NAPI_INNER_EXTERN napi_status napi_adjust_external_memory(
2411     napi_env env, int64_t change_in_bytes, int64_t* adjusted_value)
2412 {
2413     CHECK_ENV(env);
2414     CHECK_ARG(env, adjusted_value);
2415 
2416     auto engine = reinterpret_cast<NativeEngine*>(env);
2417     engine->AdjustExternalMemory(change_in_bytes, adjusted_value);
2418 
2419     return napi_clear_last_error(env);
2420 }
2421 
napi_is_callable(napi_env env,napi_value value,bool * result)2422 NAPI_EXTERN napi_status napi_is_callable(napi_env env, napi_value value, bool* result)
2423 {
2424     CHECK_ENV(env);
2425     CHECK_ARG(env, value);
2426     CHECK_ARG(env, result);
2427 
2428     auto nativeValue = LocalValueFromJsValue(value);
2429     *result = nativeValue->IsFunction();
2430 
2431     return napi_clear_last_error(env);
2432 }
2433 
napi_is_arguments_object(napi_env env,napi_value value,bool * result)2434 NAPI_EXTERN napi_status napi_is_arguments_object(napi_env env, napi_value value, bool* result)
2435 {
2436     CHECK_ENV(env);
2437     CHECK_ARG(env, value);
2438     CHECK_ARG(env, result);
2439 
2440     auto nativeValue = LocalValueFromJsValue(value);
2441     *result = nativeValue->IsArgumentsObject();
2442 
2443     return napi_clear_last_error(env);
2444 }
2445 
napi_is_async_function(napi_env env,napi_value value,bool * result)2446 NAPI_EXTERN napi_status napi_is_async_function(napi_env env, napi_value value, bool* result)
2447 {
2448     CHECK_ENV(env);
2449     CHECK_ARG(env, value);
2450     CHECK_ARG(env, result);
2451 
2452     auto nativeValue = LocalValueFromJsValue(value);
2453     *result = nativeValue->IsAsyncFunction();
2454     return napi_clear_last_error(env);
2455 }
2456 
napi_is_boolean_object(napi_env env,napi_value value,bool * result)2457 NAPI_EXTERN napi_status napi_is_boolean_object(napi_env env, napi_value value, bool* result)
2458 {
2459     CHECK_ENV(env);
2460     CHECK_ARG(env, value);
2461     CHECK_ARG(env, result);
2462 
2463     auto nativeValue = LocalValueFromJsValue(value);
2464     *result = nativeValue->IsJSPrimitiveBoolean();
2465 
2466     return napi_clear_last_error(env);
2467 }
2468 
napi_is_generator_function(napi_env env,napi_value value,bool * result)2469 NAPI_EXTERN napi_status napi_is_generator_function(napi_env env, napi_value value, bool* result)
2470 {
2471     CHECK_ENV(env);
2472     CHECK_ARG(env, value);
2473     CHECK_ARG(env, result);
2474 
2475     auto nativeValue = LocalValueFromJsValue(value);
2476     *result = nativeValue->IsGeneratorFunction();
2477 
2478     return napi_clear_last_error(env);
2479 }
2480 
napi_is_map_iterator(napi_env env,napi_value value,bool * result)2481 NAPI_EXTERN napi_status napi_is_map_iterator(napi_env env, napi_value value, bool* result)
2482 {
2483     CHECK_ENV(env);
2484     CHECK_ARG(env, value);
2485     CHECK_ARG(env, result);
2486 
2487     auto nativeValue = LocalValueFromJsValue(value);
2488     *result = nativeValue->IsMapIterator();
2489 
2490     return napi_clear_last_error(env);
2491 }
2492 
napi_is_set_iterator(napi_env env,napi_value value,bool * result)2493 NAPI_EXTERN napi_status napi_is_set_iterator(napi_env env, napi_value value, bool* result)
2494 {
2495     CHECK_ENV(env);
2496     CHECK_ARG(env, value);
2497     CHECK_ARG(env, result);
2498 
2499     auto nativeValue = LocalValueFromJsValue(value);
2500     *result = nativeValue->IsSetIterator();
2501 
2502     return napi_clear_last_error(env);
2503 }
2504 
napi_is_generator_object(napi_env env,napi_value value,bool * result)2505 NAPI_EXTERN napi_status napi_is_generator_object(napi_env env, napi_value value, bool* result)
2506 {
2507     CHECK_ENV(env);
2508     CHECK_ARG(env, value);
2509     CHECK_ARG(env, result);
2510 
2511     auto nativeValue = LocalValueFromJsValue(value);
2512     *result = nativeValue->IsGeneratorObject();
2513 
2514     return napi_clear_last_error(env);
2515 }
2516 
napi_is_module_namespace_object(napi_env env,napi_value value,bool * result)2517 NAPI_EXTERN napi_status napi_is_module_namespace_object(napi_env env, napi_value value, bool* result)
2518 {
2519     CHECK_ENV(env);
2520     CHECK_ARG(env, value);
2521     CHECK_ARG(env, result);
2522 
2523     auto nativeValue = LocalValueFromJsValue(value);
2524     *result = nativeValue->IsModuleNamespaceObject();
2525 
2526     return napi_clear_last_error(env);
2527 }
2528 
napi_is_proxy(napi_env env,napi_value value,bool * result)2529 NAPI_EXTERN napi_status napi_is_proxy(napi_env env, napi_value value, bool* result)
2530 {
2531     CHECK_ENV(env);
2532     CHECK_ARG(env, value);
2533     CHECK_ARG(env, result);
2534 
2535     auto nativeValue = LocalValueFromJsValue(value);
2536     *result = nativeValue->IsProxy();
2537     return napi_clear_last_error(env);
2538 }
2539 
napi_is_reg_exp(napi_env env,napi_value value,bool * result)2540 NAPI_EXTERN napi_status napi_is_reg_exp(napi_env env, napi_value value, bool* result)
2541 {
2542     CHECK_ENV(env);
2543     CHECK_ARG(env, value);
2544     CHECK_ARG(env, result);
2545 
2546     auto nativeValue = LocalValueFromJsValue(value);
2547     *result = nativeValue->IsRegExp();
2548     return napi_clear_last_error(env);
2549 }
2550 
napi_is_number_object(napi_env env,napi_value value,bool * result)2551 NAPI_EXTERN napi_status napi_is_number_object(napi_env env, napi_value value, bool* result)
2552 {
2553     CHECK_ENV(env);
2554     CHECK_ARG(env, value);
2555     CHECK_ARG(env, result);
2556 
2557     auto nativeValue = LocalValueFromJsValue(value);
2558     *result = nativeValue->IsJSPrimitiveNumber();
2559 
2560     return napi_clear_last_error(env);
2561 }
2562 
napi_is_map(napi_env env,napi_value value,bool * result)2563 NAPI_EXTERN napi_status napi_is_map(napi_env env, napi_value value, bool* result)
2564 {
2565     CHECK_ENV(env);
2566     CHECK_ARG(env, value);
2567     CHECK_ARG(env, result);
2568 
2569     auto nativeValue = LocalValueFromJsValue(value);
2570     *result = nativeValue->IsMap();
2571     return napi_clear_last_error(env);
2572 }
2573 
napi_is_set(napi_env env,napi_value value,bool * result)2574 NAPI_EXTERN napi_status napi_is_set(napi_env env, napi_value value, bool* result)
2575 {
2576     CHECK_ENV(env);
2577     CHECK_ARG(env, value);
2578     CHECK_ARG(env, result);
2579 
2580     auto nativeValue = LocalValueFromJsValue(value);
2581     *result = nativeValue->IsSet();
2582     return napi_clear_last_error(env);
2583 }
2584 
napi_is_string_object(napi_env env,napi_value value,bool * result)2585 NAPI_EXTERN napi_status napi_is_string_object(napi_env env, napi_value value, bool* result)
2586 {
2587     CHECK_ENV(env);
2588     CHECK_ARG(env, value);
2589     CHECK_ARG(env, result);
2590 
2591     auto nativeValue = LocalValueFromJsValue(value);
2592     *result = nativeValue->IsJSPrimitiveString();
2593 
2594     return napi_clear_last_error(env);
2595 }
2596 
napi_is_symbol_object(napi_env env,napi_value value,bool * result)2597 NAPI_EXTERN napi_status napi_is_symbol_object(napi_env env, napi_value value, bool* result)
2598 {
2599     CHECK_ENV(env);
2600     CHECK_ARG(env, value);
2601     CHECK_ARG(env, result);
2602 
2603     auto nativeValue = LocalValueFromJsValue(value);
2604     *result = nativeValue->IsJSPrimitiveSymbol();
2605     return napi_clear_last_error(env);
2606 }
2607 
napi_is_weak_map(napi_env env,napi_value value,bool * result)2608 NAPI_EXTERN napi_status napi_is_weak_map(napi_env env, napi_value value, bool* result)
2609 {
2610     CHECK_ENV(env);
2611     CHECK_ARG(env, value);
2612     CHECK_ARG(env, result);
2613 
2614     auto nativeValue = LocalValueFromJsValue(value);
2615     *result = nativeValue->IsWeakMap();
2616     return napi_clear_last_error(env);
2617 }
2618 
napi_is_weak_set(napi_env env,napi_value value,bool * result)2619 NAPI_EXTERN napi_status napi_is_weak_set(napi_env env, napi_value value, bool* result)
2620 {
2621     CHECK_ENV(env);
2622     CHECK_ARG(env, value);
2623     CHECK_ARG(env, result);
2624 
2625     auto nativeValue = LocalValueFromJsValue(value);
2626     *result = nativeValue->IsWeakSet();
2627     return napi_clear_last_error(env);
2628 }
2629 
napi_create_runtime(napi_env env,napi_env * result_env)2630 NAPI_EXTERN napi_status napi_create_runtime(napi_env env, napi_env* result_env)
2631 {
2632     CHECK_ENV(env);
2633     CHECK_ARG(env, result_env);
2634 
2635     auto engine = reinterpret_cast<NativeEngine*>(env);
2636     auto result = engine->CreateRuntime();
2637     *result_env = reinterpret_cast<napi_env>(result);
2638 
2639     return napi_clear_last_error(env);
2640 }
2641 
napi_serialize(napi_env env,napi_value object,napi_value transfer_list,napi_value clone_list,bool defaultTransfer,bool defaultCloneSendable,napi_value * result)2642 NAPI_EXTERN napi_status napi_serialize(napi_env env, napi_value object, napi_value transfer_list,
2643                                        napi_value clone_list, bool defaultTransfer, bool defaultCloneSendable,
2644                                        napi_value* result)
2645 {
2646     CHECK_ENV(env);
2647     CHECK_ARG(env, object);
2648     CHECK_ARG(env, transfer_list);
2649     CHECK_ARG(env, result);
2650 
2651     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2652     auto nativeValue = LocalValueFromJsValue(object);
2653     auto transferList = LocalValueFromJsValue(transfer_list);
2654     auto cloneList = LocalValueFromJsValue(clone_list);
2655     void* res =
2656         panda::JSNApi::SerializeValue(vm, nativeValue, transferList, cloneList, defaultTransfer, defaultCloneSendable);
2657     *result = reinterpret_cast<napi_value>(res);
2658 
2659     return napi_clear_last_error(env);
2660 }
2661 
napi_deserialize(napi_env env,napi_value recorder,napi_value * object)2662 NAPI_EXTERN napi_status napi_deserialize(napi_env env, napi_value recorder, napi_value* object)
2663 {
2664     CHECK_ENV(env);
2665     CHECK_ARG(env, recorder);
2666     CHECK_ARG(env, object);
2667 
2668     auto engine = reinterpret_cast<NativeEngine*>(env);
2669     auto vm = engine->GetEcmaVm();
2670     auto recorderValue = reinterpret_cast<void*>(recorder);
2671     Local<panda::JSValueRef> res = panda::JSNApi::DeserializeValue(vm, recorderValue, reinterpret_cast<void*>(engine));
2672     *object = JsValueFromLocalValue(res);
2673 
2674     return napi_clear_last_error(env);
2675 }
2676 
napi_delete_serialization_data(napi_env env,napi_value value)2677 NAPI_EXTERN napi_status napi_delete_serialization_data(napi_env env, napi_value value)
2678 {
2679     CHECK_ENV(env);
2680     CHECK_ARG(env, value);
2681 
2682     void* data = reinterpret_cast<void*>(value);
2683     panda::JSNApi::DeleteSerializationData(data);
2684 
2685     return napi_clear_last_error(env);
2686 }
2687 
napi_create_bigint_int64(napi_env env,int64_t value,napi_value * result)2688 NAPI_EXTERN napi_status napi_create_bigint_int64(napi_env env, int64_t value, napi_value* result)
2689 {
2690     CHECK_ENV(env);
2691     CHECK_ARG(env, result);
2692 
2693     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2694     Local<panda::BigIntRef> object = panda::BigIntRef::New(vm, value);
2695     *result = JsValueFromLocalValue(object);
2696 
2697     return napi_clear_last_error(env);
2698 }
2699 
napi_create_bigint_uint64(napi_env env,uint64_t value,napi_value * result)2700 NAPI_EXTERN napi_status napi_create_bigint_uint64(napi_env env, uint64_t value, napi_value* result)
2701 {
2702     CHECK_ENV(env);
2703     CHECK_ARG(env, result);
2704 
2705     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2706     Local<panda::BigIntRef> object = panda::BigIntRef::New(vm, value);
2707     *result = JsValueFromLocalValue(object);
2708 
2709     return napi_clear_last_error(env);
2710 }
2711 
napi_get_value_bigint_int64(napi_env env,napi_value value,int64_t * result,bool * lossless)2712 NAPI_EXTERN napi_status napi_get_value_bigint_int64(
2713     napi_env env, napi_value value, int64_t* result, bool* lossless)
2714 {
2715     CHECK_ENV(env);
2716     CHECK_ARG(env, value);
2717     CHECK_ARG(env, result);
2718     CHECK_ARG(env, lossless);
2719 
2720     auto nativeValue = LocalValueFromJsValue(value);
2721     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(), napi_bigint_expected);
2722     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2723     Local<panda::BigIntRef> bigIntVal = nativeValue->ToBigInt(vm);
2724     bigIntVal->BigIntToInt64(vm, result, lossless);
2725 
2726     return napi_clear_last_error(env);
2727 }
2728 
napi_get_value_bigint_uint64(napi_env env,napi_value value,uint64_t * result,bool * lossless)2729 NAPI_EXTERN napi_status napi_get_value_bigint_uint64(
2730     napi_env env, napi_value value, uint64_t* result, bool* lossless)
2731 {
2732     CHECK_ENV(env);
2733     CHECK_ARG(env, value);
2734     CHECK_ARG(env, result);
2735     CHECK_ARG(env, lossless);
2736 
2737     auto nativeValue = LocalValueFromJsValue(value);
2738     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(), napi_bigint_expected);
2739     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2740     Local<panda::BigIntRef> bigIntVal = nativeValue->ToBigInt(vm);
2741     bigIntVal->BigIntToUint64(vm, result, lossless);
2742 
2743     return napi_clear_last_error(env);
2744 }
2745 
napi_is_date(napi_env env,napi_value value,bool * result)2746 NAPI_EXTERN napi_status napi_is_date(napi_env env, napi_value value, bool* result)
2747 {
2748     CHECK_ENV(env);
2749     CHECK_ARG(env, value);
2750     CHECK_ARG(env, result);
2751 
2752     auto nativeValue = LocalValueFromJsValue(value);
2753     *result = nativeValue->IsDate();
2754     return napi_clear_last_error(env);
2755 }
2756 
napi_is_detached_arraybuffer(napi_env env,napi_value arraybuffer,bool * result)2757 NAPI_EXTERN napi_status napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer, bool* result)
2758 {
2759     CHECK_ENV(env);
2760     CHECK_ARG(env, arraybuffer);
2761     CHECK_ARG(env, result);
2762 
2763     auto nativeValue = LocalValueFromJsValue(arraybuffer);
2764     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2765     auto isArrayBuffer = nativeValue->IsArrayBuffer();
2766     Local<panda::ArrayBufferRef> bufObj = nativeValue->ToObject(vm);
2767     if (isArrayBuffer) {
2768         *result = bufObj->IsDetach();
2769     } else {
2770         return napi_set_last_error(env, napi_invalid_arg);
2771     }
2772     return napi_clear_last_error(env);
2773 }
2774 
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)2775 NAPI_EXTERN napi_status napi_get_all_property_names(
2776     napi_env env, napi_value object, napi_key_collection_mode key_mode,
2777     napi_key_filter key_filter, napi_key_conversion key_conversion, napi_value* result)
2778 {
2779     NAPI_PREAMBLE(env);
2780     CHECK_ARG(env, object);
2781     CHECK_ARG(env, result);
2782 
2783     auto nativeValue = LocalValueFromJsValue(object);
2784     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject() || nativeValue->IsFunction(), napi_object_expected);
2785     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2786     Local<panda::ObjectRef> obj = nativeValue->ToObject(vm);
2787     uint32_t filter = NATIVE_DEFAULT;
2788     if (key_filter & napi_key_writable) {
2789         filter = static_cast<uint32_t>(filter | NATIVE_WRITABLE);
2790     }
2791     if (key_filter & napi_key_enumerable) {
2792         filter = static_cast<uint32_t>(filter | NATIVE_ENUMERABLE);
2793     }
2794     if (key_filter & napi_key_configurable) {
2795         filter = static_cast<uint32_t>(filter | NATIVE_CONFIGURABLE);
2796     }
2797     if (key_filter & napi_key_skip_strings) {
2798         filter = static_cast<uint32_t>(filter | NATIVE_KEY_SKIP_STRINGS);
2799     }
2800     if (key_filter & napi_key_skip_symbols) {
2801         filter = static_cast<uint32_t>(filter | NATIVE_KEY_SKIP_SYMBOLS);
2802     }
2803 
2804     switch (key_mode) {
2805         case napi_key_include_prototypes:
2806             filter = static_cast<uint32_t>(filter | NATIVE_KEY_INCLUDE_PROTOTYPES);
2807             break;
2808         case napi_key_own_only:
2809             filter = static_cast<uint32_t>(filter | NATIVE_KEY_OWN_ONLY);
2810             break;
2811         default:
2812             *result = nullptr;
2813             return napi_set_last_error(env, napi_invalid_arg);
2814     }
2815 
2816     switch (key_conversion) {
2817         case napi_key_keep_numbers:
2818             filter = static_cast<uint32_t>(filter | NATIVE_KEY_KEEP_NUMBERS);
2819             break;
2820         case napi_key_numbers_to_strings:
2821             filter = static_cast<uint32_t>(filter | NATIVE_KEY_NUMBERS_TO_STRINGS);
2822             break;
2823         default:
2824             *result = nullptr;
2825             return napi_set_last_error(env, napi_invalid_arg);
2826     }
2827     Local<panda::ArrayRef> arrayVal = obj->GetAllPropertyNames(vm, filter);
2828     *result = JsValueFromLocalValue(arrayVal);
2829     return GET_RETURN_STATUS(env);
2830 }
2831 
napi_detach_arraybuffer(napi_env env,napi_value arraybuffer)2832 NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer)
2833 {
2834     CHECK_ENV(env);
2835     CHECK_ARG(env, arraybuffer);
2836 
2837     auto nativeValue = LocalValueFromJsValue(arraybuffer);
2838     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
2839     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2840     auto isArrayBuffer = nativeValue->IsArrayBuffer();
2841     Local<panda::ArrayBufferRef> bufObj = nativeValue->ToObject(vm);
2842     if (isArrayBuffer) {
2843         if (!bufObj->IsDetach()) {
2844             bufObj->Detach(vm);
2845         }
2846     } else {
2847         return napi_set_last_error(env, napi_invalid_arg);
2848     }
2849     return napi_clear_last_error(env);
2850 }
2851 
napi_type_tag_object(napi_env env,napi_value js_object,const napi_type_tag * type_tag)2852 NAPI_EXTERN napi_status napi_type_tag_object(napi_env env, napi_value js_object, const napi_type_tag* type_tag)
2853 {
2854     NAPI_PREAMBLE(env);
2855     CHECK_ARG(env, js_object);
2856     CHECK_ARG(env, type_tag);
2857 
2858     auto nativeValue = LocalValueFromJsValue(js_object);
2859     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
2860     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2861     auto obj = nativeValue->ToObject(vm);
2862     NapiTypeTag* typeTag = (NapiTypeTag*)type_tag;
2863     const char name[] = "ACENAPI_TYPETAG";
2864     bool hasPribate = false;
2865     bool result = true;
2866     Local<panda::StringRef> key = StringRef::NewFromUtf8(vm, name);
2867     hasPribate = obj->Has(vm, key);
2868     if (!hasPribate) {
2869         constexpr int bigintMod = 2; // 2 : used for even number judgment
2870         int sign_bit = 0;
2871         size_t word_count = 2;
2872         bool sign = false;
2873         if ((sign_bit % bigintMod) == 1) {
2874             sign = true;
2875         }
2876         uint32_t size = (uint32_t)word_count;
2877         Local<panda::JSValueRef> value = panda::BigIntRef::CreateBigWords(vm, sign, size,
2878                                                                           reinterpret_cast<const uint64_t*>(typeTag));
2879         Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
2880         result = obj->Set(vm, key, value);
2881     }
2882     if (!result) {
2883         return napi_set_last_error(env, napi_invalid_arg);
2884     }
2885 
2886     return napi_clear_last_error(env);
2887 }
2888 
BigIntGetWordsArray(Local<panda::BigIntRef> & value,int * signBit,size_t * wordCount,uint64_t * words)2889 bool BigIntGetWordsArray(Local<panda::BigIntRef> &value, int* signBit, size_t* wordCount, uint64_t* words)
2890 {
2891     if (wordCount == nullptr) {
2892         return false;
2893     }
2894     size_t size = static_cast<size_t>(value->GetWordsArraySize());
2895     if (signBit == nullptr && words == nullptr) {
2896         *wordCount = size;
2897         return true;
2898     } else if (signBit != nullptr && words != nullptr) {
2899         if (size > *wordCount) {
2900             size = *wordCount;
2901         }
2902         bool sign = false;
2903         value->GetWordsArray(&sign, size, words);
2904         if (sign) {
2905             *signBit = 1;
2906         } else {
2907             *signBit = 0;
2908         }
2909         *wordCount = size;
2910         return true;
2911     }
2912     return false;
2913 }
2914 
napi_check_object_type_tag(napi_env env,napi_value js_object,const napi_type_tag * type_tag,bool * result)2915 NAPI_EXTERN napi_status napi_check_object_type_tag(napi_env env,
2916                                                    napi_value js_object,
2917                                                    const napi_type_tag* type_tag,
2918                                                    bool* result)
2919 {
2920     NAPI_PREAMBLE(env);
2921     CHECK_ARG(env, js_object);
2922     CHECK_ARG(env, type_tag);
2923     CHECK_ARG(env, result);
2924 
2925     auto nativeValue = LocalValueFromJsValue(js_object);
2926     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
2927     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2928     auto obj = nativeValue->ToObject(vm);
2929     NapiTypeTag* typeTag = (NapiTypeTag*)type_tag;
2930     *result = false;
2931     const char name[] = "ACENAPI_TYPETAG";
2932 
2933     Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
2934     *result = obj->Has(vm, key);
2935     if (*result) {
2936         Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
2937         Local<panda::JSValueRef> object = obj->Get(vm, key);
2938         if (object->IsBigInt()) {
2939             int sign;
2940             size_t size = 2; // 2: Indicates that the number of elements is 2
2941             NapiTypeTag tag;
2942             Local<panda::BigIntRef> bigintObj = object->ToBigInt(vm);
2943             BigIntGetWordsArray(bigintObj, &sign, &size, reinterpret_cast<uint64_t*>(&tag));
2944             if (sign == 0 && ((size == 1) || (size == 2))) { // 2: Indicates that the number of elements is 2
2945                 *result = (tag.lower == typeTag->lower && tag.upper == typeTag->upper);
2946             }
2947         }
2948     }
2949     return napi_clear_last_error(env);
2950 }
2951 
napi_create_date(napi_env env,double time,napi_value * result)2952 NAPI_EXTERN napi_status napi_create_date(napi_env env, double time, napi_value* result)
2953 {
2954     NAPI_PREAMBLE(env);
2955     CHECK_ARG(env, result);
2956 
2957     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2958     *result = JsValueFromLocalValue(DateRef::New(vm, time));
2959 
2960     return napi_clear_last_error(env);
2961 }
2962 
napi_get_date_value(napi_env env,napi_value value,double * result)2963 NAPI_EXTERN napi_status napi_get_date_value(napi_env env, napi_value value, double* result)
2964 {
2965     NAPI_PREAMBLE(env);
2966     CHECK_ARG(env, value);
2967     CHECK_ARG(env, result);
2968 
2969     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2970     auto nativeValue = LocalValueFromJsValue(value);
2971     auto IsDate_result = nativeValue->IsDate();
2972     Local<panda::DateRef> dateObj = nativeValue->ToObject(vm);
2973     if (IsDate_result) {
2974         *result = dateObj->GetTime();
2975     } else {
2976         return napi_set_last_error(env, napi_date_expected);
2977     }
2978 
2979     return napi_clear_last_error(env);
2980 }
2981 
napi_add_finalizer(napi_env env,napi_value js_object,void * native_object,napi_finalize finalize_cb,void * finalize_hint,napi_ref * result)2982 NAPI_EXTERN napi_status napi_add_finalizer(napi_env env,
2983                                            napi_value js_object,
2984                                            void* native_object,
2985                                            napi_finalize finalize_cb,
2986                                            void* finalize_hint,
2987                                            napi_ref* result)
2988 {
2989     CHECK_ENV(env);
2990     CHECK_ARG(env, js_object);
2991     CHECK_ARG(env, finalize_cb);
2992 
2993     auto nativeValue = LocalValueFromJsValue(js_object);
2994     auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
2995     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
2996     NativeReference* reference = nullptr;
2997     auto engine = reinterpret_cast<NativeEngine*>(env);
2998     if (result != nullptr) {
2999         reference = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
3000         *result = reinterpret_cast<napi_ref>(reference);
3001     } else {
3002         reference = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
3003     }
3004     return napi_clear_last_error(env);
3005 }
3006 
napi_create_bigint_words(napi_env env,int sign_bit,size_t word_count,const uint64_t * words,napi_value * result)3007 NAPI_EXTERN napi_status napi_create_bigint_words(napi_env env,
3008                                                  int sign_bit,
3009                                                  size_t word_count,
3010                                                  const uint64_t* words,
3011                                                  napi_value* result)
3012 {
3013     NAPI_PREAMBLE(env);
3014     CHECK_ARG(env, words);
3015     CHECK_ARG(env, result);
3016     RETURN_STATUS_IF_FALSE(env, word_count <= INT_MAX, napi_invalid_arg);
3017 
3018     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3019     constexpr int bigintMod = 2; // 2 : used for even number judgment
3020     bool sign = false;
3021     if ((sign_bit % bigintMod) == 1) {
3022         sign = true;
3023     }
3024     uint32_t size = (uint32_t)word_count;
3025     Local<panda::JSValueRef> value = panda::BigIntRef::CreateBigWords(vm, sign, size, words);
3026 
3027     if (panda::JSNApi::HasPendingException(vm)) {
3028         return napi_set_last_error(env, napi_pending_exception);
3029     }
3030     *result = JsValueFromLocalValue(value);
3031     return GET_RETURN_STATUS(env);
3032 }
3033 
napi_get_value_bigint_words(napi_env env,napi_value value,int * sign_bit,size_t * word_count,uint64_t * words)3034 NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env,
3035                                                     napi_value value,
3036                                                     int* sign_bit,
3037                                                     size_t* word_count,
3038                                                     uint64_t* words)
3039 {
3040     CHECK_ENV(env);
3041     CHECK_ARG(env, value);
3042     CHECK_ARG(env, word_count);
3043 
3044     auto nativeValue = LocalValueFromJsValue(value);
3045     RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(), napi_object_expected);
3046     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3047     auto BigintObj = nativeValue->ToBigInt(vm);
3048     if (word_count == nullptr) {
3049         return napi_set_last_error(env, napi_invalid_arg);
3050     }
3051     size_t size = static_cast<size_t>(BigintObj->GetWordsArraySize());
3052     if (sign_bit == nullptr && words == nullptr) {
3053         *word_count = size;
3054         return napi_set_last_error(env, napi_ok);
3055     } else if (sign_bit != nullptr && words != nullptr) {
3056         if (size > *word_count) {
3057             size = *word_count;
3058         }
3059         bool sign = false;
3060         BigintObj->GetWordsArray(&sign, size, words);
3061         if (sign) {
3062             *sign_bit = 1;
3063         } else {
3064             *sign_bit = 0;
3065         }
3066         *word_count = size;
3067         return napi_set_last_error(env, napi_ok);
3068     }
3069 
3070     return napi_clear_last_error(env);
3071 }
3072 
napi_run_script_path(napi_env env,const char * path,napi_value * result)3073 NAPI_EXTERN napi_status napi_run_script_path(napi_env env, const char* path, napi_value* result)
3074 {
3075     NAPI_PREAMBLE(env);
3076     CHECK_ARG(env, result);
3077 
3078     auto engine = reinterpret_cast<NativeEngine*>(env);
3079     *result = engine->RunScript(path);
3080     return GET_RETURN_STATUS(env);
3081 }
3082 
napi_is_big_int64_array(napi_env env,napi_value value,bool * result)3083 NAPI_EXTERN napi_status napi_is_big_int64_array(napi_env env, napi_value value, bool* result)
3084 {
3085     CHECK_ENV(env);
3086     CHECK_ARG(env, value);
3087     CHECK_ARG(env, result);
3088 
3089     auto nativeValue = LocalValueFromJsValue(value);
3090     *result = nativeValue->IsBigInt64Array();
3091     return napi_clear_last_error(env);
3092 }
3093 
napi_is_big_uint64_array(napi_env env,napi_value value,bool * result)3094 NAPI_EXTERN napi_status napi_is_big_uint64_array(napi_env env, napi_value value, bool* result)
3095 {
3096     CHECK_ENV(env);
3097     CHECK_ARG(env, value);
3098     CHECK_ARG(env, result);
3099 
3100     auto nativeValue = LocalValueFromJsValue(value);
3101     *result = nativeValue->IsBigUint64Array();
3102     return napi_clear_last_error(env);
3103 }
3104 
napi_is_shared_array_buffer(napi_env env,napi_value value,bool * result)3105 NAPI_EXTERN napi_status napi_is_shared_array_buffer(napi_env env, napi_value value, bool* result)
3106 {
3107     CHECK_ENV(env);
3108     CHECK_ARG(env, value);
3109     CHECK_ARG(env, result);
3110 
3111     auto nativeValue = LocalValueFromJsValue(value);
3112     *result = nativeValue->IsSharedArrayBuffer();
3113     return napi_clear_last_error(env);
3114 }
3115 
napi_get_stack_trace(napi_env env,std::string & stack)3116 NAPI_EXTERN napi_status napi_get_stack_trace(napi_env env, std::string& stack)
3117 {
3118     CHECK_ENV(env);
3119 
3120     auto engine = reinterpret_cast<NativeEngine*>(env);
3121     [[maybe_unused]] auto vm = engine->GetEcmaVm();
3122     std::string rawStack;
3123 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
3124     DFXJSNApi::BuildJsStackTrace(vm, rawStack);
3125 #else
3126     HILOG_WARN("GetStacktrace env get stack failed");
3127 #endif
3128     stack = engine->ExecuteTranslateBySourceMap(rawStack);
3129     return napi_clear_last_error(env);
3130 }
3131 
napi_object_get_keys(napi_env env,napi_value data,napi_value * result)3132 NAPI_EXTERN napi_status napi_object_get_keys(napi_env env, napi_value data, napi_value* result)
3133 {
3134     CHECK_ENV(env);
3135 
3136     auto nativeValue = LocalValueFromJsValue(data);
3137     RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(), napi_object_expected);
3138     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3139     auto obj = nativeValue->ToObject(vm);
3140     Local<panda::ArrayRef> arrayVal = obj->GetOwnEnumerablePropertyNames(vm);
3141 
3142     *result = JsValueFromLocalValue(arrayVal);
3143     return napi_clear_last_error(env);
3144 }
3145 
napi_queue_async_work_with_qos(napi_env env,napi_async_work work,napi_qos_t qos)3146 NAPI_EXTERN napi_status napi_queue_async_work_with_qos(napi_env env, napi_async_work work, napi_qos_t qos)
3147 {
3148     CHECK_ENV(env);
3149     CHECK_ARG(env, work);
3150 
3151     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
3152     asyncWork->QueueWithQos(qos);
3153     return napi_status::napi_ok;
3154 }
3155 
DetachFuncCallback(void * engine,void * object,void * hint,void * detachData)3156 void* DetachFuncCallback(void* engine, void* object, void* hint, void* detachData)
3157 {
3158     if (detachData == nullptr || (engine == nullptr || object ==nullptr)) {
3159         HILOG_ERROR("DetachFuncCallback params has nullptr");
3160         return nullptr;
3161     }
3162     DetachCallback detach = reinterpret_cast<DetachCallback>(detachData);
3163     void* detachVal = detach(reinterpret_cast<NativeEngine*>(engine), object, hint);
3164     return detachVal;
3165 }
3166 
AttachFuncCallback(void * engine,void * buffer,void * hint,void * attachData)3167 Local<panda::JSValueRef> AttachFuncCallback(void* engine, void* buffer, void* hint, void* attachData)
3168 {
3169     if (attachData == nullptr || (engine == nullptr || buffer ==nullptr)) {
3170         HILOG_ERROR("AttachFuncCallback params has nullptr");
3171     }
3172     auto vm = reinterpret_cast<NativeEngine*>(engine)->GetEcmaVm();
3173     EscapeLocalScope scope(vm);
3174     Local<panda::JSValueRef> result = panda::JSValueRef::Undefined(vm);
3175     NapiAttachCallback attach = reinterpret_cast<NapiAttachCallback>(attachData);
3176     napi_value attachVal = attach(reinterpret_cast<napi_env>(engine), buffer, hint);
3177     if (attachVal == nullptr) {
3178         HILOG_WARN("AttachFunc return nullptr");
3179     } else {
3180         result = LocalValueFromJsValue(attachVal);
3181     }
3182     return scope.Escape(result);
3183 }
3184 
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)3185 NAPI_EXTERN napi_status napi_coerce_to_native_binding_object(napi_env env,
3186                                                              napi_value js_object,
3187                                                              napi_native_binding_detach_callback detach_cb,
3188                                                              napi_native_binding_attach_callback attach_cb,
3189                                                              void* native_object,
3190                                                              void* hint)
3191 {
3192     CHECK_ENV(env);
3193     CHECK_ARG(env, js_object);
3194     CHECK_ARG(env, detach_cb);
3195     CHECK_ARG(env, attach_cb);
3196     CHECK_ARG(env, native_object);
3197 
3198     auto jsValue = LocalValueFromJsValue(js_object);
3199     RETURN_STATUS_IF_FALSE(env, jsValue->IsObject(), napi_object_expected);
3200     auto engine = reinterpret_cast<NativeEngine*>(env);
3201     auto vm = engine->GetEcmaVm();
3202     auto obj = jsValue->ToObject(vm);
3203 
3204     panda::JSNApi::NativeBindingInfo* data = panda::JSNApi::NativeBindingInfo::CreateNewInstance();
3205     if (data == nullptr) {
3206         HILOG_ERROR("data is nullptr");
3207         return napi_set_last_error(env, napi_invalid_arg);
3208     }
3209     data->env = env;
3210     data->nativeValue = native_object;
3211     data->attachFunc = reinterpret_cast<void*>(AttachFuncCallback);
3212     data->attachData = reinterpret_cast<void*>(attach_cb);
3213     data->detachFunc = reinterpret_cast<void*>(DetachFuncCallback);
3214     data->detachData = reinterpret_cast<void*>(detach_cb);
3215     data->hint = hint;
3216 
3217     size_t nativeBindingSize = 7 * sizeof(void *); // 7 : params num
3218     Local<panda::NativePointerRef> value = panda::NativePointerRef::New(vm, data,
3219         [](void* data, void* info) {
3220             auto externalInfo = reinterpret_cast<panda::JSNApi::NativeBindingInfo*>(data);
3221             delete externalInfo;
3222         }, nullptr, nativeBindingSize);
3223 
3224     bool res = obj->ConvertToNativeBindingObject(vm, value);
3225     if (res) {
3226         return napi_clear_last_error(env);
3227     }
3228     return napi_status::napi_generic_failure;
3229 }
3230 
napi_get_print_string(napi_env env,napi_value value,std::string & result)3231 NAPI_EXTERN napi_status napi_get_print_string(napi_env env, napi_value value, std::string& result)
3232 {
3233     CHECK_ENV(env);
3234     CHECK_ARG(env, value);
3235 
3236     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3237     auto nativeValue = LocalValueFromJsValue(value);
3238     if (nativeValue->IsString()) {
3239         Local<panda::StringRef> stringVal = nativeValue->ToString(vm);
3240         result = stringVal->ToString();
3241     }
3242     return napi_clear_last_error(env);
3243 }
3244 
napi_run_module_path(napi_env env,const char * path,const char * entryPoint,napi_value * result)3245 NAPI_EXTERN napi_status napi_run_module_path(napi_env env, const char* path, const char* entryPoint, napi_value* result)
3246 {
3247     CHECK_ENV(env);
3248     CHECK_ARG(env, result);
3249 
3250     auto engine = reinterpret_cast<NativeEngine*>(env);
3251     *result = engine->RunScriptForAbc(path, const_cast<char*>(entryPoint));
3252     return napi_clear_last_error(env);
3253 }
3254