diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 9304c250da36791750ce8c252601fb55451f50f8..c7ba81d7b1290454fb5077ab6b740fa906f99007 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -181,6 +181,38 @@ NAPI_EXTERN napi_status napi_get_shared_array_buffer_info(napi_env env, napi_value arraybuffer, void** data, size_t* byte_length); + +/** + * @brief Takes ownership of an ArrayBuffer Object's buffer. + * + * After this call, the ArrayBuffer will be detached and unusable. + * + * @param env The native engine environment. + * @param arraybuffer The ArrayBuffer whose ownership will be taken. + * @param data [out] Pointer to receive the data buffer of the ArrayBuffer. + * @param byte_length [out] Pointer to receive the byte length of the ArrayBuffer. + * @param finalize_cb [out] Pointer to receive the finalizer callback. + * @param finalize_hint [out] Pointer to receive the finalizer hint. + * @param is_external [out] Pointer to receive whether the ArrayBuffer is external. + * + * @return napi_status The status code indicating success or failure. + */ +NAPI_EXTERN napi_status napi_release_buffer_arraybuffer(napi_env env, + napi_value arraybuffer, + void** data, + size_t* byte_length, + napi_finalize* finalize_cb, + void** finalize_hint, + bool* is_external); +NAPI_EXTERN napi_status napi_is_external_arraybuffer(napi_env env, napi_value arraybuffer, bool* result); +NAPI_EXTERN napi_status napi_get_arraybuffer_finalizer(napi_env env, + napi_value arraybuffer, + napi_finalize* finalize_cb_ptr, + void** finalize_hint_ptr); +NAPI_EXTERN napi_status napi_set_arraybuffer_finalizer(napi_env env, + napi_value arraybuffer, + napi_finalize finalize_cb, + void* finalize_hint); NAPI_EXTERN napi_status napi_encode(napi_env env, napi_value src, napi_value* result); NAPI_EXTERN napi_status napi_is_bitvector(napi_env env, napi_value value, bool* result); NAPI_EXTERN napi_status napi_set_stackinfo(napi_env env, napi_stack_info *napi_info); diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index 1ca7312fff5ab1be2db53bf44d295e24487478bd..60ce80dc4ac694ae5b5627326101ddb2ac2a3189 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -14,6 +14,7 @@ */ #ifndef NAPI_EXPERIMENTAL #define NAPI_EXPERIMENTAL +#include #endif #ifdef ENABLE_CONTAINER_SCOPE @@ -2637,6 +2638,139 @@ NAPI_EXTERN napi_status napi_get_arraybuffer_info(napi_env env, return napi_clear_last_error(env); } +NAPI_EXTERN napi_status napi_release_buffer_arraybuffer(napi_env env, + napi_value arraybuffer, + void** data, + size_t* byte_length, + napi_finalize* finalize_cb, + void** finalize_hint, + bool* is_external) +{ + CHECK_ENV(env); + CHECK_ARG(env, arraybuffer); + CHECK_ARG(env, data); + CHECK_ARG(env, byte_length); + CHECK_ARG(env, finalize_cb); + CHECK_ARG(env, finalize_hint); + CHECK_ARG(env, is_external); + + auto nativeValue = LocalValueFromJsValue(arraybuffer); + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::JsiFastNativeScope fastNativeScope(vm); + if (LIKELY(nativeValue->IsArrayBuffer(vm))) { + Local res(nativeValue); + + // Get the data and byte length + if (data != nullptr) { + *data = res->GetBuffer(vm); + } + *byte_length = res->ByteLength(vm); + + // Check if the ArrayBuffer is external + bool withNativeAreaAllocator = res->GetWithNativeAreaAllocator(vm); + *is_external = !withNativeAreaAllocator; + + if (!withNativeAreaAllocator) { + // If the ArrayBuffer is external, get the finalizer callback and hint + auto [finalize_cb_, finalize_hint_] = res->GetFinalizer(vm); + if (finalize_cb != nullptr) { + *finalize_cb = reinterpret_cast(finalize_cb_); + } + if (finalize_hint != nullptr) { + *finalize_hint = finalize_hint_; + } + } + + // Release the ArrayBuffer + res->SetFinalizer(vm, nullptr, nullptr); + res->DetachForTransferring(vm); + } else { + // TODO: should we check if the SendableArrayBuffer is external? + return napi_set_last_error(env, napi_arraybuffer_expected); + } + + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_is_external_arraybuffer(napi_env env, napi_value arraybuffer, bool* result) +{ + CHECK_ENV(env); + CHECK_ARG(env, arraybuffer); + + auto nativeValue = LocalValueFromJsValue(arraybuffer); + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::JsiFastNativeScope fastNativeScope(vm); + if (LIKELY(nativeValue->IsArrayBuffer(vm))) { + Local res(nativeValue); + + bool withNativeAreaAllocator = res->GetWithNativeAreaAllocator(vm); + + *result = !withNativeAreaAllocator; + } else { + // TODO: should we check if the SendableArrayBuffer is external? + return napi_set_last_error(env, napi_arraybuffer_expected); + } + + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_get_arraybuffer_finalizer(napi_env env, + napi_value arraybuffer, + napi_finalize* finalize_cb_ptr, + void** finalize_hint_ptr) +{ + CHECK_ENV(env); + CHECK_ARG(env, arraybuffer); + CHECK_ARG(env, finalize_cb_ptr); + CHECK_ARG(env, finalize_hint_ptr); + + auto nativeValue = LocalValueFromJsValue(arraybuffer); + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::JsiFastNativeScope fastNativeScope(vm); + if (LIKELY(nativeValue->IsArrayBuffer(vm))) { + Local res(nativeValue); + auto [finalize_cb, finalize_hint] = res->GetFinalizer(vm); + + if (finalize_cb_ptr != nullptr) { + *finalize_cb_ptr = reinterpret_cast(finalize_cb); + } + if (finalize_hint_ptr != nullptr) { + *finalize_hint_ptr = finalize_hint; + } + } else if (nativeValue->IsSendableArrayBuffer(vm)) { + // TODO + } else { + return napi_set_last_error(env, napi_arraybuffer_expected); + } + + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_set_arraybuffer_finalizer(napi_env env, + napi_value arraybuffer, + napi_finalize finalize_cb, + void* finalize_hint) +{ + CHECK_ENV(env); + CHECK_ARG(env, arraybuffer); + // CHECK_ARG(env, finalize_cb); + // CHECK_ARG(env, finalize_hint); + + auto nativeValue = LocalValueFromJsValue(arraybuffer); + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::JsiFastNativeScope fastNativeScope(vm); + if (LIKELY(nativeValue->IsArrayBuffer(vm))) { + Local res(nativeValue); + res->SetFinalizer(vm, reinterpret_cast(finalize_cb), finalize_hint); + } else if (nativeValue->IsSendableArrayBuffer(vm)) { + // TODO + } else { + return napi_set_last_error(env, napi_arraybuffer_expected); + } + + return napi_clear_last_error(env); +} + NAPI_EXTERN napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) { CHECK_ENV(env); @@ -4426,7 +4560,7 @@ NAPI_EXTERN napi_status napi_vm_handshake(napi_env env, return napi_clear_last_error(env); } -NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref, std::function &visitor) +NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref, std::function& visitor) { NAPI_PREAMBLE(env); CHECK_ARG(env, ref); @@ -4444,7 +4578,7 @@ NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref) return napi_clear_last_error(env); } -NAPI_EXTERN napi_status napi_is_alive_object(napi_env env, napi_ref ref, bool *result) +NAPI_EXTERN napi_status napi_is_alive_object(napi_env env, napi_ref ref, bool* result) { NAPI_PREAMBLE(env); CHECK_ARG(env, ref); @@ -4453,7 +4587,7 @@ NAPI_EXTERN napi_status napi_is_alive_object(napi_env env, napi_ref ref, bool *r return napi_clear_last_error(env); } -NAPI_EXTERN napi_status napi_is_contain_object(napi_env env, napi_ref ref, bool *result) +NAPI_EXTERN napi_status napi_is_contain_object(napi_env env, napi_ref ref, bool* result) { NAPI_PREAMBLE(env); CHECK_ARG(env, ref); @@ -4509,7 +4643,8 @@ NAPI_EXTERN napi_status napi_wrap_with_xref(napi_env env, data->attachXRefFunc = reinterpret_cast(proxy_cb); data->attachXRefData = native_object; object->SetNativePointerFieldCount(vm, 1); - object->SetNativePointerField(vm, 0, ref, + object->SetNativePointerField( + vm, 0, ref, [](void* env, void* data, void* info) { panda::JSNApi::XRefBindingInfo* externalInfo = reinterpret_cast(info); delete externalInfo;