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