From 6bcfd909b8674551866ca549e86a898f863cb940 Mon Sep 17 00:00:00 2001 From: benzunfu Date: Tue, 24 Jun 2025 20:45:37 +0800 Subject: [PATCH] Fix 1.2 napi_serialize problem iIssue:https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICHHIB Signed-off-by: benzunfu Change-Id: I293ff6576c2fe2c05f33812e3738af3a81d33acb --- interfaces/inner_api/napi/native_node_api.h | 12 +++ native_engine/native_api.cpp | 15 +++- native_engine/native_node_api.cpp | 84 +++++++++++++++++++++ test/unittest/test_napi.cpp | 45 ++++++++--- 4 files changed, 146 insertions(+), 10 deletions(-) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 5dbcd8dc5..6cff6901a 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -29,6 +29,7 @@ typedef void (*NAPIGetJSCode)(const char** buf, int* bufLen); typedef void (*NapiNativeFinalize)(napi_env env, void* data, void* hint); typedef void* (*NapiDetachCallback)(napi_env env, void* nativeObject, void* hint); // hint: detach params typedef napi_value (*NapiAttachCallback)(napi_env env, void* nativeObject, void* hint); // hint: attach params +typedef napi_value (*proxy_object_attach_cb)(napi_env env, void* data); typedef struct napi_fast_native_scope__* napi_fast_native_scope; typedef struct napi_module_with_js { @@ -209,15 +210,26 @@ NAPI_EXTERN napi_status napi_create_xref(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref* result); +NAPI_EXTERN napi_status napi_mark_attach_with_xref(napi_env env, + napi_value js_object, + void *attach_data, + proxy_object_attach_cb attach_cb); NAPI_EXTERN napi_status napi_wrap_with_xref(napi_env env, napi_value js_object, void* native_object, napi_finalize finalize_cb, + proxy_object_attach_cb proxy_cb, napi_ref* result); NAPI_EXTERN napi_status napi_is_alive_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_EXTERN napi_status napi_is_xref_type(napi_env env, napi_value js_object, bool* result); NAPI_EXTERN napi_status napi_get_ets_implements(napi_env env, napi_value value, napi_value* result); +NAPI_EXTERN napi_status napi_serialize_hybrid(napi_env env, + napi_value object, + napi_value transfer_list, + napi_value clone_list, + void** result); +NAPI_EXTERN napi_status napi_deserialize_hybrid(napi_env env, void* buffer, napi_value* object); #endif // PANDA_JS_ETS_HYBRID_MODE NAPI_EXTERN napi_status napi_register_appstate_callback(napi_env env, NapiAppStateCallback callback); diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index d3d17439f..fc764e994 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -4479,6 +4479,7 @@ NAPI_EXTERN napi_status napi_wrap_with_xref(napi_env env, napi_value js_object, void* native_object, napi_finalize finalize_cb, + proxy_object_attach_cb proxy_cb, napi_ref* result) { NAPI_PREAMBLE(env); @@ -4501,8 +4502,20 @@ NAPI_EXTERN napi_status napi_wrap_with_xref(napi_env env, // Create strong reference now, will update to weak reference after interop support ref = engine->CreateXRefReference(js_object, 1, false, callback, native_object); *reference = ref; + panda::JSNApi::XRefBindingInfo* data = panda::JSNApi::XRefBindingInfo::CreateNewInstance(); + if (data == nullptr) { + HILOG_ERROR("data is nullptr"); + return napi_set_last_error(env, napi_invalid_arg); + } + data->attachXRefFunc = reinterpret_cast(proxy_cb); + data->attachXRefData = native_object; object->SetNativePointerFieldCount(vm, 1); - object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize); + object->SetNativePointerField(vm, 0, ref, + [](void* env, void* data, void* info) { + panda::JSNApi::XRefBindingInfo* externalInfo = reinterpret_cast(info); + delete externalInfo; + }, + reinterpret_cast(data), nativeBindingSize); PropertyAttribute attr(object, true, false, true); nativeObject->DefineProperty(vm, key, attr); return GET_RETURN_STATUS(env); diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index 830b43961..47d987da9 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -16,9 +16,15 @@ #include "native_api_internal.h" #include "native_engine/native_async_hook_context.h" #include "native_engine/native_utils.h" +#ifdef PANDA_JS_ETS_HYBRID_MODE +#include "ecmascript/napi/include/jsnapi.h" +#include "ecmascript/napi/include/jsnapi_expo.h" +#include "native_engine/impl/ark/ark_native_reference.h" +#endif // PANDA_JS_ETS_HYBRID_MODE using panda::Local; using panda::StringRef; +using panda::ObjectRef; static constexpr int32_t MAX_THREAD_SAFE_COUNT = 128; @@ -638,3 +644,81 @@ NAPI_EXTERN napi_status napi_get_ets_implements(napi_env env, napi_value value, *result = JsValueFromLocalValue(implementsValue); return GET_RETURN_STATUS(env); } + +#ifdef PANDA_JS_ETS_HYBRID_MODE +NAPI_EXTERN napi_status napi_serialize_hybrid(napi_env env, + napi_value object, + napi_value transfer_list, + napi_value clone_list, + void** result) +{ + CHECK_ENV(env); + CHECK_ARG(env, object); + CHECK_ARG(env, transfer_list); + CHECK_ARG(env, clone_list); + CHECK_ARG(env, result); + + auto vm = reinterpret_cast(env)->GetEcmaVm(); + auto nativeValue = LocalValueFromJsValue(object); + auto transferList = LocalValueFromJsValue(transfer_list); + RETURN_STATUS_IF_FALSE(env, transferList->IsUndefined() || transferList->IsJSArray(vm), napi_invalid_arg); + auto cloneList = LocalValueFromJsValue(clone_list); + RETURN_STATUS_IF_FALSE(env, cloneList->IsUndefined() || cloneList->IsJSArray(vm), napi_invalid_arg); + *result = panda::JSNApi::InterOpSerializeValue(vm, nativeValue, transferList, cloneList, false, false); + + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_deserialize_hybrid(napi_env env, void* buffer, napi_value* object) +{ + CHECK_ENV(env); + CHECK_ARG(env, buffer); + CHECK_ARG(env, object); + + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + Local res = panda::JSNApi::InterOpDeserializeValue(vm, buffer, reinterpret_cast(engine)); + *object = JsValueFromLocalValue(res); + + return napi_clear_last_error(env); +} + + +NAPI_EXTERN napi_status napi_mark_attach_with_xref(napi_env env, + napi_value js_object, + void *attach_data, + proxy_object_attach_cb attach_cb) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, js_object); + CHECK_ARG(env, attach_data); + CHECK_ARG(env, attach_cb); + + auto nativeValue = LocalValueFromJsValue(js_object); + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + panda::JsiFastNativeScope fastNativeScope(vm); + CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject); + size_t nativeBindingSize = 0; + Local key = panda::StringRef::GetProxyNapiWrapperString(vm); + Local object = panda::ObjectRef::NewJSXRefObject(vm); + // Create strong reference now, will update to weak reference after interop support + panda::JSNApi::XRefBindingInfo* data = panda::JSNApi::XRefBindingInfo::CreateNewInstance(); + if (data == nullptr) { + HILOG_ERROR("data is nullptr"); + return napi_set_last_error(env, napi_invalid_arg); + } + data->attachXRefFunc = reinterpret_cast(attach_cb); + data->attachXRefData = attach_data; + object->SetNativePointerFieldCount(vm, 1); + object->SetNativePointerField(vm, 0, nullptr, + [](void* env, void* data, void* info) { + panda::JSNApi::XRefBindingInfo* externalInfo = reinterpret_cast(info); + delete externalInfo; + }, + reinterpret_cast(data), nativeBindingSize); + PropertyAttribute attr(object, true, false, true); + nativeObject->DefineProperty(vm, key, attr); + return GET_RETURN_STATUS(env); +} +#endif // PANDA_JS_ETS_HYBRID_MODE \ No newline at end of file diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index 78285de1b..3fc43e02a 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -7634,7 +7634,7 @@ HWTEST_F(NapiBasicTest, NapiWrapWithXRefTest001, testing::ext::TestSize.Level1) napi_create_object(env, &obj); napi_status status = napi_wrap_with_xref( - env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_ok); } @@ -7646,7 +7646,7 @@ HWTEST_F(NapiBasicTest, NapiWrapWithXRefTest002, testing::ext::TestSize.Level1) napi_create_object(env, &obj); napi_status status = napi_wrap_with_xref( - env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_ok); } @@ -7657,7 +7657,7 @@ HWTEST_F(NapiBasicTest, NapiWrapWithXRefTest003, testing::ext::TestSize.Level1) napi_ref result; napi_status status = napi_wrap_with_xref( - env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_invalid_arg); } @@ -7669,7 +7669,7 @@ HWTEST_F(NapiBasicTest, NapiWrapWithXRefTest004, testing::ext::TestSize.Level1) napi_create_object(env, &obj); napi_status status = napi_wrap_with_xref( - env, obj, nullptr, [](napi_env, void* data, void* hint) {}, &result); + env, obj, nullptr, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_invalid_arg); } @@ -7680,7 +7680,7 @@ HWTEST_F(NapiBasicTest, NapiWrapWithXRefTest005, testing::ext::TestSize.Level1) napi_ref result; napi_create_object(env, &obj); - napi_status status = napi_wrap_with_xref(env, obj, (void*)TEST_STRING, nullptr, &result); + napi_status status = napi_wrap_with_xref(env, obj, (void*)TEST_STRING, nullptr, nullptr, &result); ASSERT_EQ(status, napi_invalid_arg); } @@ -7691,7 +7691,7 @@ HWTEST_F(NapiBasicTest, NapiWrapWithXRefTest006, testing::ext::TestSize.Level1) napi_ref result; napi_create_object(env, &obj); - napi_status status = napi_wrap_with_xref(env, obj, (void*)TEST_STRING, nullptr, &result); + napi_status status = napi_wrap_with_xref(env, obj, (void*)TEST_STRING, nullptr, nullptr, &result); ASSERT_EQ(status, napi_invalid_arg); } @@ -7703,7 +7703,7 @@ HWTEST_F(NapiBasicTest, NapiMarkFromObjectTest001, testing::ext::TestSize.Level1 napi_create_object(env, &obj); napi_status status = napi_wrap_with_xref( - env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_ok); status = napi_mark_from_object(env, result); ASSERT_EQ(status, napi_ok); @@ -7743,6 +7743,33 @@ HWTEST_F(NapiBasicTest, NapiCreateXRefTest003, testing::ext::TestSize.Level1) auto res = napi_create_xref(env, nullptr, 1, nullptr); ASSERT_EQ(res, napi_invalid_arg); } + +HWTEST_F(NapiBasicTest, NapiCreateXRefTest004, testing::ext::TestSize.Level1) +{ + ASSERT_NE(engine_, nullptr); + napi_env env = reinterpret_cast(engine_); + + auto res = napi_serialize_hybrid(env, nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(res, napi_invalid_arg); +} + +HWTEST_F(NapiBasicTest, NapiCreateXRefTest005, testing::ext::TestSize.Level1) +{ + ASSERT_NE(engine_, nullptr); + napi_env env = reinterpret_cast(engine_); + + auto res = napi_deserialize_hybrid(env, nullptr, nullptr); + ASSERT_EQ(res, napi_invalid_arg); +} + +HWTEST_F(NapiBasicTest, NapiCreateXRefTest006, testing::ext::TestSize.Level1) +{ + ASSERT_NE(engine_, nullptr); + napi_env env = reinterpret_cast(engine_); + + auto res = napi_mark_attach_with_xref(env, nullptr, nullptr, nullptr); + ASSERT_EQ(res, napi_invalid_arg); +} #endif HWTEST_F(NapiBasicTest, NapiRegisterAppStateCallbakcTest001, testing::ext::TestSize.Level1) @@ -8926,7 +8953,7 @@ HWTEST_F(NapiBasicTest, NapiIsAliveObjectTest001, testing::ext::TestSize.Level1) napi_create_object(env, &obj); napi_status status = - napi_wrap_with_xref(env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + napi_wrap_with_xref(env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_ok); status = napi_is_alive_object(env, result, &res); ASSERT_EQ(status, napi_ok); @@ -8941,7 +8968,7 @@ HWTEST_F(NapiBasicTest, NapiIsValidHeapObjectTest001, testing::ext::TestSize.Lev napi_create_object(env, &obj); napi_status status = - napi_wrap_with_xref(env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + napi_wrap_with_xref(env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, nullptr, &result); ASSERT_EQ(status, napi_ok); status = napi_is_contain_object(env, result, &res); ASSERT_EQ(status, napi_ok); -- Gitee