From e079ff7982a4121ec25399ecfb73ae8ffe413b11 Mon Sep 17 00:00:00 2001 From: AnBetter Date: Fri, 11 Apr 2025 14:17:53 +0800 Subject: [PATCH 01/17] Implementation of GC DFX Issue: [Feature]: https://gitee.com/openharmony/arkui_napi/issues/IC0DAS Reason: Implementation of GC DFX Description: Implementation of GC DFX Change-Id: Ic8931c816cc9a4783f3d2f6f968fef51d1710541 Signed-off-by: AnBetter --- interfaces/inner_api/napi/native_node_api.h | 3 ++ test/unittest/test_napi.cpp | 41 +++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index ddea4adee..6977afa05 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -234,6 +234,9 @@ NAPI_EXTERN napi_status napi_wrap_with_xref(napi_env env, void* native_object, napi_finalize finalize_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); #endif // PANDA_JS_ETS_HYBRID_MODE 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); diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index 8fa34980a..c4179cb44 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -9055,6 +9055,47 @@ HWTEST_F(NapiBasicTest, NapiGetValueBigintInt64Test004, testing::ext::TestSize.L ASSERT_EQ(status, napi_bigint_expected); } +HWTEST_F(NapiBasicTest, NapiIsAliveObjectTest001, testing::ext::TestSize.Level1) +{ + napi_env env = reinterpret_cast(engine_); + napi_value obj; + napi_ref result = nullptr; + bool res = false; + + napi_create_object(env, &obj); + napi_status status = + napi_wrap_with_xref(env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + ASSERT_EQ(status, napi_ok); + status = napi_is_alive_object(env, result, &res); + ASSERT_EQ(status, napi_ok); +} + +HWTEST_F(NapiBasicTest, NapiIsValidHeapObjectTest001, testing::ext::TestSize.Level1) +{ + napi_env env = reinterpret_cast(engine_); + napi_value obj; + napi_ref result = nullptr; + bool res = false; + + napi_create_object(env, &obj); + napi_status status = + napi_wrap_with_xref(env, obj, (void*)TEST_STRING, [](napi_env, void* data, void* hint) {}, &result); + ASSERT_EQ(status, napi_ok); + status = napi_is_contain_object(env, result, &res); + ASSERT_EQ(status, napi_ok); +} + +HWTEST_F(NapiBasicTest, NapiIsXrefTypeTest001, testing::ext::TestSize.Level1) +{ + napi_env env = reinterpret_cast(engine_); + napi_value obj; + bool res = false; + + napi_create_object(env, &obj); + napi_status status = napi_is_xref_type(env, obj, &res); + ASSERT_EQ(status, napi_ok); +} + HWTEST_F(NapiBasicTest, NapiGetValueBigintInt64Test005, testing::ext::TestSize.Level1) { napi_env env = reinterpret_cast(engine_); -- Gitee From e3430f7d930efaade7a5887f393bd0419247f3cb Mon Sep 17 00:00:00 2001 From: zhao1d Date: Sat, 24 May 2025 20:10:02 +0800 Subject: [PATCH 02/17] =?UTF-8?q?napi=E9=80=82=E9=85=8D1.0=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E9=80=82=E9=85=8D1.2=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E6=97=B6=E7=9A=84interface(0328)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAAIG Signed-off-by: zhao1d Change-Id: I20533daacec0004418f3dd52f27d8d4081fd1697 --- interfaces/inner_api/napi/native_node_api.h | 1 + native_engine/native_node_api.cpp | 13 +++++++++++++ test/unittest/test_napi.cpp | 15 +++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 6977afa05..9666925e3 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -237,6 +237,7 @@ NAPI_EXTERN napi_status napi_wrap_with_xref(napi_env env, 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); #endif // PANDA_JS_ETS_HYBRID_MODE 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); diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index 3fb1b0d89..1a994e5bd 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -644,3 +644,16 @@ NAPI_EXTERN napi_status napi_set_module_validate_callback(napi_module_validate_c } return napi_generic_failure; } +NAPI_EXTERN napi_status napi_get_ets_implements(napi_env env, napi_value value, napi_value* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); + + auto nativeValue = LocalValueFromJsValue(value); + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + Local implementsValue = panda::JSNApi::GetImplements(vm, nativeValue); + *result = JsValueFromLocalValue(implementsValue); + return GET_RETURN_STATUS(env); +} diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index c4179cb44..add504d59 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -8281,6 +8281,21 @@ HWTEST_F(NapiBasicTest, NapiMakeCallbackTest002, testing::ext::TestSize.Level1) ASSERT_EQ(status, napi_invalid_arg); } +/** + * @tc.name: NapiGetEtsImplementsTest + * @tc.desc: Test interface of napi_get_ets_implements + * @tc.type: FUNC + */ +HWTEST_F(NapiBasicTest, NapiGetEtsImplementsTest, testing::ext::TestSize.Level1) +{ + napi_env env = reinterpret_cast(engine_); + napi_value value = nullptr; + napi_value result = nullptr; + + napi_status status = napi_get_ets_implements(env, value, &result); + ASSERT_EQ(status, napi_invalid_arg); +} + HWTEST_F(NapiBasicTest, NapiAsyncDestroyTest001, testing::ext::TestSize.Level1) { napi_env env = reinterpret_cast(engine_); -- Gitee From 63f447c51fc50f0bf338bcf87d914eeb345d285f Mon Sep 17 00:00:00 2001 From: chentianyu Date: Tue, 10 Jun 2025 16:49:44 +0800 Subject: [PATCH 03/17] xref adapt to cmc-gc Signed-off-by: chentianyu Change-Id: I60b520f6ed432ab951a874c11196fda3b9e7be9c --- interfaces/inner_api/napi/native_node_api.h | 1 + native_engine/impl/ark/ark_native_reference.cpp | 5 +++++ native_engine/impl/ark/ark_native_reference.h | 1 + native_engine/native_api.cpp | 9 +++++++++ 4 files changed, 16 insertions(+) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 9666925e3..f99790bc7 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -224,6 +224,7 @@ NAPI_EXTERN napi_status napi_xref_wrap(napi_env env, napi_ref* result); NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, void** result); +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); NAPI_EXTERN napi_status napi_create_xref(napi_env env, napi_value value, diff --git a/native_engine/impl/ark/ark_native_reference.cpp b/native_engine/impl/ark/ark_native_reference.cpp index 2a7ec59c7..706dfea2b 100644 --- a/native_engine/impl/ark/ark_native_reference.cpp +++ b/native_engine/impl/ark/ark_native_reference.cpp @@ -358,6 +358,11 @@ inline void ArkNativeReference::SetFinalRan() } #ifdef PANDA_JS_ETS_HYBRID_MODE +void ArkNativeReference::MarkFromObject(std::function &visitor) +{ + value_.MarkFromObject(visitor); +} + void ArkNativeReference::MarkFromObject() { value_.MarkFromObject(); diff --git a/native_engine/impl/ark/ark_native_reference.h b/native_engine/impl/ark/ark_native_reference.h index 10c272843..9ead72981 100644 --- a/native_engine/impl/ark/ark_native_reference.h +++ b/native_engine/impl/ark/ark_native_reference.h @@ -96,6 +96,7 @@ public: napi_value GetNapiValue() override; void ResetFinalizer() override; #ifdef PANDA_JS_ETS_HYBRID_MODE + void MarkFromObject(std::function &visitor); void MarkFromObject(); bool IsObjectAlive(); bool IsValidHeapObject(); diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index 6c2db3166..4efa1b4c1 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -4732,6 +4732,15 @@ 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_PREAMBLE(env); + CHECK_ARG(env, ref); + ArkNativeReference* reference = reinterpret_cast(ref); + reference->MarkFromObject(visitor); + return napi_clear_last_error(env); +} + NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref) { NAPI_PREAMBLE(env); -- Gitee From 943bbd38515658145e6c02676ca5bed1f1aace3e Mon Sep 17 00:00:00 2001 From: Rokashevich Svetlana Date: Thu, 17 Apr 2025 19:11:54 +0300 Subject: [PATCH 04/17] Change ace_napi dep for ark_hybrid Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICGHB6 Signed-off-by: Rokashevich Svetlana Change-Id: I941c12215e3f9fd1625f597efeabd0ceebda1775 --- BUILD.gn | 6 +++++- interfaces/inner_api/cjffi/ark_interop/BUILD.gn | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index bea2f299f..9872151b1 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -196,7 +196,6 @@ ohos_source_set("ace_napi_static") { configs += [ "${ets_runtime_path}:ark_jsruntime_public_config" ] } else { external_deps += [ - "ets_runtime:libark_jsruntime", "icu:shared_icui18n", "icu:shared_icuuc", "libuv:uv", @@ -204,6 +203,11 @@ ohos_source_set("ace_napi_static") { if (!ark_standalone_build) { external_deps += [ "node:node_header_notice" ] } + if (defined(ark_hybrid) && ark_hybrid) { + external_deps += [ "runtime_core:libarkruntime" ] + } else { + external_deps += [ "ets_runtime:libark_jsruntime" ] + } } cflags_cc = [ "-Wno-missing-braces" ] diff --git a/interfaces/inner_api/cjffi/ark_interop/BUILD.gn b/interfaces/inner_api/cjffi/ark_interop/BUILD.gn index c09ff8dc3..0db8ecf9b 100644 --- a/interfaces/inner_api/cjffi/ark_interop/BUILD.gn +++ b/interfaces/inner_api/cjffi/ark_interop/BUILD.gn @@ -83,7 +83,12 @@ ohos_shared_library("ark_interop") { "../../../..:ace_napi", ] - external_deps = [ "ets_runtime:libark_jsruntime" ] + external_deps = [] + if (defined(ark_hybrid) && ark_hybrid) { + external_deps += [ "runtime_core:libarkruntime" ] + } else { + external_deps += [ "ets_runtime:libark_jsruntime" ] + } if (!ark_standalone_build) { external_deps += [ "hilog:libhilog" ] -- Gitee From 6e8a2753ef1ca35b4ef299d15d868ff29842cfe4 Mon Sep 17 00:00:00 2001 From: yangzk Date: Mon, 23 Jun 2025 14:42:01 +0800 Subject: [PATCH 05/17] =?UTF-8?q?Description:=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=80=9A=E8=BF=87nativeModuleManager=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=92=8C=E8=8E=B7=E5=8F=96Dl=5Fnamespace=20IssueNo:#ICGTGD=20S?= =?UTF-8?q?ig:=20SIG=5FApplicationFramework=20Feature=20or=20Bugfix:=20Bug?= =?UTF-8?q?fix=20Binary=20Source:=20No?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangzk Change-Id: I0bc98926b092d09b81b33a4bb3ea0558efd4380e --- module_manager/native_module_manager.cpp | 15 +++++++++++++++ module_manager/native_module_manager.h | 1 + .../module_manager_test/module_manager_test.cpp | 12 ++++++++++++ 3 files changed, 28 insertions(+) diff --git a/module_manager/native_module_manager.cpp b/module_manager/native_module_manager.cpp index 0b43b0b34..d5e7be299 100644 --- a/module_manager/native_module_manager.cpp +++ b/module_manager/native_module_manager.cpp @@ -502,6 +502,21 @@ void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const #endif } +bool NativeModuleManager::GetLdNamespaceName(const std::string &moduleName, std::string &nsName) +{ +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \ + !defined(LINUX_PLATFORM) + if (nsMap_.find(moduleName) == nsMap_.end()) { + HILOG_ERROR("not found ns: %{public}s", moduleName.c_str()); + return false; + } + nsName = "moduleNs_" + moduleName; + return true; +#else + return false; +#endif +} + void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector& appLibPath, const bool& isSystemApp) { diff --git a/module_manager/native_module_manager.h b/module_manager/native_module_manager.h index 73563033b..6ac3f8819 100644 --- a/module_manager/native_module_manager.h +++ b/module_manager/native_module_manager.h @@ -86,6 +86,7 @@ public: void Register(NativeModule* nativeModule); void SetAppLibPath(const std::string& moduleName, const std::vector& appLibPath, const bool& isSystemApp = false); + bool GetLdNamespaceName(const std::string &moduleName, std::string &nsName); NativeModule* LoadNativeModule(const char* moduleName, const char* path, bool isAppModule, std::string& errInfo, bool internal = false, const char* relativePath = ""); void SetNativeEngine(std::string moduleName, NativeEngine* nativeEngine); diff --git a/module_manager/test/unittest/module_manager_test/module_manager_test.cpp b/module_manager/test/unittest/module_manager_test/module_manager_test.cpp index 9722ade09..6298d806a 100644 --- a/module_manager/test/unittest/module_manager_test/module_manager_test.cpp +++ b/module_manager/test/unittest/module_manager_test/module_manager_test.cpp @@ -227,7 +227,13 @@ HWTEST_F(ModuleManagerTest, LoadNativeModuleTest_008, TestSize.Level1) moduleManager->Register(nullptr); moduleManager->CreateSharedLibsSonames(); + std::string nsName; + bool res = moduleManager->GetLdNamespaceName(moduleName, nsName); + EXPECT_EQ(res, false); moduleManager->CreateLdNamespace(moduleName, libPath, true); + res = moduleManager->GetLdNamespaceName(moduleName, nsName); + EXPECT_EQ(res, true); + EXPECT_STREQ(nsName.c_str(), ("moduleNs_" + moduleName).c_str()); GTEST_LOG_(INFO) << "ModuleManagerTest, LoadNativeModuleTest_008 end"; } @@ -245,7 +251,13 @@ HWTEST_F(ModuleManagerTest, LoadNativeModuleTest_009, TestSize.Level1) std::shared_ptr moduleManager = std::make_shared(); ASSERT_NE(nullptr, moduleManager); + std::string nsName; + bool res = moduleManager->GetLdNamespaceName(moduleName, nsName); + EXPECT_EQ(res, false); moduleManager->CreateLdNamespace(moduleName, libPath, false); + res = moduleManager->GetLdNamespaceName(moduleName, nsName); + EXPECT_EQ(res, true); + EXPECT_STREQ(nsName.c_str(), ("moduleNs_" + moduleName).c_str()); std::vector appLibPath; moduleManager->SetAppLibPath(moduleName, appLibPath, false); GTEST_LOG_(INFO) << "ModuleManagerTest, LoadNativeModuleTest_009 end"; -- Gitee From 7e1be873bc6dbc4a196f121613492a1281aabf96 Mon Sep 17 00:00:00 2001 From: benzunfu Date: Tue, 24 Jun 2025 20:45:37 +0800 Subject: [PATCH 06/17] 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 f99790bc7..f3fb0a494 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -30,6 +30,7 @@ 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 bool (*napi_module_validate_callback)(const char* moduleName); +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 { @@ -230,15 +231,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_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); diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index 4efa1b4c1..006ae8fdf 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -4784,6 +4784,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); @@ -4806,8 +4807,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 1a994e5bd..dcd8eced0 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -17,9 +17,15 @@ #include "native_engine/native_async_hook_context.h" #include "native_engine/native_utils.h" #include "native_engine/impl/ark/ark_native_engine.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; @@ -657,3 +663,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 add504d59..3c97a433e 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -7778,7 +7778,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); } @@ -7790,7 +7790,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); } @@ -7801,7 +7801,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); } @@ -7813,7 +7813,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); } @@ -7824,7 +7824,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); } @@ -7835,7 +7835,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); } @@ -7847,7 +7847,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); @@ -7887,6 +7887,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) @@ -9079,7 +9106,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); @@ -9094,7 +9121,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 From bf31a78beb19ea14cba327512f2006d92b790a0d Mon Sep 17 00:00:00 2001 From: kurnevichstanislav Date: Fri, 27 Jun 2025 17:06:56 +0300 Subject: [PATCH 07/17] Avoid overloading in interface Issue: https://gitee.com/openharmony/arkui_napi/issues/ICIEJC?from=project-issue Signed-off-by: kurnevichstanislav Change-Id: I8f6dbf5488a0c0cbf2546b30565c82827d1c8852 --- interfaces/inner_api/napi/native_node_api.h | 3 ++- native_engine/native_api.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index f3fb0a494..115904b14 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -225,7 +225,8 @@ NAPI_EXTERN napi_status napi_xref_wrap(napi_env env, napi_ref* result); NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, void** result); -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_for_cmc(napi_env env, napi_ref ref, + std::function &visitor); NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref); NAPI_EXTERN napi_status napi_create_xref(napi_env env, napi_value value, diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index 006ae8fdf..320702503 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -4732,7 +4732,8 @@ 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_for_cmc(napi_env env, napi_ref ref, + std::function &visitor) { NAPI_PREAMBLE(env); CHECK_ARG(env, ref); -- Gitee From e1629840927b9d7c742377ba6429c073cedc8c2d Mon Sep 17 00:00:00 2001 From: z00932658 Date: Wed, 4 Jun 2025 16:56:38 +0800 Subject: [PATCH 08/17] Fix isHybrid for napi Issue: https://gitee.com/openharmony/ability_ability_runtime/issues/ICD2ZO Signed-off-by: zhushihao Change-Id: I768896756a16f7ef6b6a6b88b94a676d9b12ef01 --- interfaces/inner_api/napi/native_node_api.h | 4 +++ native_engine/impl/ark/ark_native_engine.cpp | 31 ++++++++++++++++++-- native_engine/impl/ark/ark_native_engine.h | 3 +- native_engine/native_api.cpp | 7 ++--- native_engine/native_engine.h | 3 +- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 115904b14..03762ed93 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -68,6 +68,10 @@ typedef enum { using NapiAppStateCallback = void (*)(int state, int64_t timestamp); +NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, + const char* path, + const char* module_info, + napi_value* result); NAPI_EXTERN napi_status napi_create_limit_runtime(napi_env env, napi_env* result_env); NAPI_EXTERN void napi_module_with_js_register(napi_module_with_js* mod); NAPI_EXTERN napi_status napi_is_callable(napi_env env, napi_value value, bool* result); diff --git a/native_engine/impl/ark/ark_native_engine.cpp b/native_engine/impl/ark/ark_native_engine.cpp index 0684a2489..4715f4eb9 100644 --- a/native_engine/impl/ark/ark_native_engine.cpp +++ b/native_engine/impl/ark/ark_native_engine.cpp @@ -1863,7 +1863,7 @@ napi_value ArkNativeEngine::NapiLoadModule(const char* path) return JsValueFromLocalValue(scope.Escape(exportObj)); } -napi_value ArkNativeEngine::NapiLoadModuleWithInfo(const char* path, const char* module_info, bool isHybrid) +napi_value ArkNativeEngine::NapiLoadModuleWithInfo(const char* path, const char* module_info) { if (path == nullptr) { HILOG_ERROR("ArkNativeEngine:The module name is empty"); @@ -1876,7 +1876,34 @@ napi_value ArkNativeEngine::NapiLoadModuleWithInfo(const char* path, const char* std::string modulePath; if (module_info != nullptr) { modulePath = module_info; - exportObj = panda::JSNApi::GetModuleNameSpaceWithModuleInfo(vm_, inputPath, modulePath, isHybrid); + exportObj = panda::JSNApi::GetModuleNameSpaceWithModuleInfoForNormalApp(vm_, inputPath, modulePath); + } else { + exportObj = NapiLoadNativeModule(inputPath); + } + + if (panda::JSNApi::HasPendingException(vm_)) { + HILOG_WARN("ArkNativeEngine:NapiLoadModuleWithInfo failed."); + panda::JSNApi::PrintExceptionInfo(vm_); + panda::JSNApi::GetAndClearUncaughtException(vm_); // clear exception here + return JsValueFromLocalValue(scope.Escape(undefObj)); + } + return JsValueFromLocalValue(scope.Escape(exportObj)); +} + +napi_value ArkNativeEngine::NapiLoadModuleWithInfoForHybridApp(const char* path, const char* module_info) +{ + if (path == nullptr) { + HILOG_ERROR("ArkNativeEngine:The module name is empty"); + return nullptr; + } + panda::EscapeLocalScope scope(vm_); + Local undefObj = JSValueRef::Undefined(vm_); + Local exportObj(undefObj); + std::string inputPath(path); + std::string modulePath; + if (module_info != nullptr) { + modulePath = module_info; + exportObj = panda::JSNApi::GetModuleNameSpaceWithModuleInfoForHybridApp(vm_, inputPath, modulePath); } else { exportObj = NapiLoadNativeModule(inputPath); } diff --git a/native_engine/impl/ark/ark_native_engine.h b/native_engine/impl/ark/ark_native_engine.h index 82040cd4f..47ab97607 100644 --- a/native_engine/impl/ark/ark_native_engine.h +++ b/native_engine/impl/ark/ark_native_engine.h @@ -347,7 +347,8 @@ public: const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param, const std::string& instanceName, void** instance); napi_value NapiLoadModule(const char* path) override; - napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info, bool isHybrid = false) override; + napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info) override; + napi_value NapiLoadModuleWithInfoForHybridApp(const char* path, const char* module_info) override; std::string GetOhmurl(std::string str); Local NapiLoadNativeModule(std::string path); NativeReference* GetPromiseRejectCallBackRef() diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index 320702503..8408b9c05 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -3295,13 +3295,12 @@ NAPI_EXTERN napi_status napi_load_module_with_info(napi_env env, NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, const char* path, const char* module_info, - napi_value* result, - bool isHybrid) + napi_value* result) { NAPI_PREAMBLE(env); CHECK_ARG(env, result); auto engine = reinterpret_cast(env); - *result = engine->NapiLoadModuleWithInfo(path, module_info, isHybrid); + *result = engine->NapiLoadModuleWithInfoForHybridApp(path, module_info); return GET_RETURN_STATUS(env); } // Memory management @@ -4604,7 +4603,7 @@ NAPI_EXTERN napi_status napi_load_module_with_module_request(napi_env env, const if (request_name[0] == NAME_SPACE_TAG) { // load module with OhmUrl auto [path, module_info] = panda::JSNApi::ResolveOhmUrl(request_name); - napi_load_module_with_info_hybrid(env, path.c_str(), module_info.c_str(), result, true); + napi_load_module_with_info_hybrid(env, path.c_str(), module_info.c_str(), result); } else { napi_load_module_with_path(env, request_name, result); } diff --git a/native_engine/native_engine.h b/native_engine/native_engine.h index c3bd0abb6..54ab66e3d 100644 --- a/native_engine/native_engine.h +++ b/native_engine/native_engine.h @@ -521,7 +521,8 @@ public: void SetModuleLoadChecker(const std::shared_ptr& moduleCheckerDelegate); virtual napi_value NapiLoadModule(const char* path) = 0; - virtual napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info, bool isHybrid = false) = 0; + virtual napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info) = 0; + virtual napi_value NapiLoadModuleWithInfoForHybridApp(const char* path, const char* module_info) = 0; virtual std::string GetPkgName(const std::string &moduleName) = 0; double NewAsyncId() -- Gitee From a0b9e76f097a097b8a5759fa4386b658224cf48a Mon Sep 17 00:00:00 2001 From: z00932658 Date: Thu, 26 Jun 2025 10:11:50 +0800 Subject: [PATCH 09/17] Add tests for NapiLoadModuleWithInfoForHybridApp Issue: https://gitee.com/openharmony/ability_ability_runtime/issues/ICD2ZO Signed-off-by: zhushihao --- test/unittest/test_napi.cpp | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index 3c97a433e..142a6439a 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -13742,6 +13742,46 @@ HWTEST_F(NapiBasicTest, NapiLoadModuleWithInfoTest004, testing::ext::TestSize.Le ASSERT_EQ(result2->error_code, napi_generic_failure); } +/** + * @tc.name: NapiLoadModuleWithInfoForHybridAppTest + * @tc.desc: Test interface of napi_load_module_with_info_hybrid + * @tc.type: FUNC + */ +HWTEST_F(NapiBasicTest, NapiLoadModuleWithInfoForHybridAppTest001, testing::ext::TestSize.Level1) +{ + auto res = napi_load_module_with_info_hybrid(nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(res, napi_invalid_arg); +} + +/** + * @tc.name: NapiLoadModuleWithInfoForHybridAppTest + * @tc.desc: Test interface of napi_load_module_with_info_hybrid + * @tc.type: FUNC + */ +HWTEST_F(NapiBasicTest, NapiLoadModuleWithInfoForHybridAppTest002, testing::ext::TestSize.Level1) +{ + ASSERT_NE(engine_, nullptr); + napi_env env = reinterpret_cast(engine_); + + auto res = napi_load_module_with_info_hybrid(env, nullptr, nullptr, nullptr); + ASSERT_EQ(res, napi_invalid_arg); +} + +/** + * @tc.name: NapiLoadModuleWithInfoForHybridAppTest + * @tc.desc: Test interface of napi_load_module_with_info_hybrid + * @tc.type: FUNC + */ +HWTEST_F(NapiBasicTest, NapiLoadModuleWithInfoForHybridAppTest003, testing::ext::TestSize.Level1) +{ + ASSERT_NE(engine_, nullptr); + napi_env env = reinterpret_cast(engine_); + + napi_value result = nullptr; + auto res = napi_load_module_with_info_hybrid(env, nullptr, nullptr, &result); + ASSERT_EQ(res, napi_ok); +} + /** * @tc.name: NapiSerializeTest * @tc.desc: Test interface of napi_serialize -- Gitee From c2eb4af6860388c2e090d994aa86e7122976f05e Mon Sep 17 00:00:00 2001 From: z00932658 Date: Wed, 9 Jul 2025 18:57:20 +0800 Subject: [PATCH 10/17] Merge 0328 to 0702 Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICJYED Signed-off-by: zhushihao Change-Id: I1fa0b6ce07af65e1ae3e43559553fc1cce5926a4 --- native_engine/native_node_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index dcd8eced0..293cf09d0 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -736,7 +736,7 @@ NAPI_EXTERN napi_status napi_mark_attach_with_xref(napi_env env, delete externalInfo; }, reinterpret_cast(data), nativeBindingSize); - PropertyAttribute attr(object, true, false, true); + panda::PropertyAttribute attr(object, true, false, true); nativeObject->DefineProperty(vm, key, attr); return GET_RETURN_STATUS(env); } -- Gitee From ce65dbe6498988ec45a5d31d87b6ad672bd82b74 Mon Sep 17 00:00:00 2001 From: zhao1d Date: Mon, 14 Jul 2025 09:53:46 +0800 Subject: [PATCH 11/17] napi adapt 1.2runtime interface cherrypick 0702 Signed-off-by: zhao1d Change-Id: I288494f51c70c7ecda01599d7ad61dac7de241d3 --- interfaces/inner_api/napi/native_node_api.h | 1 + native_engine/native_node_api.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 03762ed93..55fd95c78 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -256,6 +256,7 @@ NAPI_EXTERN napi_status napi_serialize_hybrid(napi_env env, napi_value clone_list, void** result); NAPI_EXTERN napi_status napi_deserialize_hybrid(napi_env env, void* buffer, napi_value* object); +NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env); #endif // PANDA_JS_ETS_HYBRID_MODE 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); diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index 293cf09d0..60de7ea63 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -740,4 +740,14 @@ NAPI_EXTERN napi_status napi_mark_attach_with_xref(napi_env env, nativeObject->DefineProperty(vm, key, attr); return GET_RETURN_STATUS(env); } + +NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env) +{ + NAPI_PREAMBLE(env); + + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + panda::JSNApi::InitHybridVMEnv(vm); + return GET_RETURN_STATUS(env); +} #endif // PANDA_JS_ETS_HYBRID_MODE \ No newline at end of file -- Gitee From 5d64324a660415a59982bfd3000a8872cb837c53 Mon Sep 17 00:00:00 2001 From: oh_ci Date: Tue, 15 Jul 2025 12:14:31 +0000 Subject: [PATCH 12/17] update .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md. Signed-off-by: oh_ci --- .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md index c650180a2..893124270 100644 --- a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -54,9 +54,9 @@ - [ ] 已检查,可开机 - [ ] 不涉及,无需验证 -### L0新增用例自检结果 -- [ ] 是,有新增L0用例,且完成自检 -- [ ] 否 +### 是否已执行L0用例 +- [ ] 已验证 +- [ ] 不涉及。如不涉及,请写明理由 ### 将上述测试的截图贴到下面 -- Gitee From bb27ab939717e9316281655fbce07536ee98607e Mon Sep 17 00:00:00 2001 From: jiangmingcheng Date: Fri, 4 Jul 2025 11:57:05 +0800 Subject: [PATCH 13/17] =?UTF-8?q?Refactor=20napi=201.2=20Related=20Interfa?= =?UTF-8?q?ces=E2=80=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: [Bug]: https://gitee.com/openharmony/arkui_napi/issues/ICLCHA Signed-off-by: jiangmingcheng Change-Id: Ida1b79691757a658e6bb5c31c9b463c1e302e680 --- bundle.json | 3 +- interfaces/inner_api/napi/native_node_api.h | 104 +---- .../inner_api/napi/native_node_hybrid_api.h | 107 +++++ napi.gni | 3 +- native_engine/native_api.cpp | 267 +----------- native_engine/native_engine.h | 3 +- native_engine/native_node_api.cpp | 110 +---- native_engine/native_node_hybrid_api.cpp | 395 ++++++++++++++++++ test/unittest/test_napi.cpp | 3 +- 9 files changed, 531 insertions(+), 464 deletions(-) create mode 100644 interfaces/inner_api/napi/native_node_hybrid_api.h create mode 100644 native_engine/native_node_hybrid_api.cpp diff --git a/bundle.json b/bundle.json index 3145e934b..465457429 100644 --- a/bundle.json +++ b/bundle.json @@ -71,7 +71,8 @@ "header_base": "//foundation/arkui/napi/interfaces/inner_api", "header_files": [ "napi/native_common.h", - "napi/native_node_api.h" + "napi/native_node_api.h", + "napi/native_node_hybrid_api.h" ] }, "name": "//foundation/arkui/napi:ace_napi" diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 55fd95c78..699c910f4 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -22,15 +22,14 @@ #include #include "js_native_api.h" -#include "node_api.h" #include "native_common.h" +#include "node_api.h" 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 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 bool (*napi_module_validate_callback)(const char* moduleName); -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 { @@ -44,11 +43,6 @@ typedef struct napi_module_with_js { NAPIGetJSCode nm_get_js_code = nullptr; } napi_module_with_js; -typedef struct napi_stack_info { - size_t stack_start; - size_t stack_size; -} napi_stack_info; - typedef enum { napi_eprio_vip = 0, napi_eprio_immediate = 1, @@ -57,31 +51,25 @@ typedef enum { napi_eprio_idle = 4, } napi_event_priority; -typedef enum { - NAPI_APP_STATE_FOREGROUND = 0, - NAPI_APP_STATE_BACKGROUND = 1, - NAPI_APP_STATE_SENSITIVE_START = 2, - NAPI_APP_STATE_SENSITIVE_END = 3, - NAPI_APP_STATE_COLD_START_FINISHED = 4, - NAPI_APP_STATE_WARM_START = 5, -} NapiAppState; - -using NapiAppStateCallback = void (*)(int state, int64_t timestamp); - -NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, - const char* path, - const char* module_info, - napi_value* result); NAPI_EXTERN napi_status napi_create_limit_runtime(napi_env env, napi_env* result_env); NAPI_EXTERN void napi_module_with_js_register(napi_module_with_js* mod); NAPI_EXTERN napi_status napi_is_callable(napi_env env, napi_value value, bool* result); NAPI_EXTERN napi_status napi_create_runtime(napi_env env, napi_env* result_env); -NAPI_EXTERN napi_status napi_serialize_inner(napi_env env, napi_value object, napi_value transfer_list, - napi_value clone_list, bool defaultTransfer, bool defaultCloneSendable, +NAPI_EXTERN napi_status napi_serialize_inner(napi_env env, + napi_value object, + napi_value transfer_list, + napi_value clone_list, + bool defaultTransfer, + bool defaultCloneSendable, void** result); -NAPI_EXTERN napi_status 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); +NAPI_EXTERN napi_status 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); NAPI_EXTERN napi_status napi_run_actor(napi_env env, const char* path, char* entryPoint, @@ -204,68 +192,12 @@ NAPI_EXTERN napi_status napi_remove_cleanup_finalizer(napi_env env, void (*fun)( * @return napi_status The status of the operation. Returns napi_ok if successful. */ NAPI_EXTERN napi_status napi_set_module_validate_callback(napi_module_validate_callback check_callback); -NAPI_EXTERN napi_status napi_set_stackinfo(napi_env env, napi_stack_info *napi_info); -NAPI_EXTERN napi_status napi_get_stackinfo(napi_env env, napi_stack_info *result); NAPI_EXTERN napi_status napi_load_module_with_path(napi_env env, const char* path, napi_value* result); -NAPI_EXTERN napi_status napi_load_module_with_module_request(napi_env env, const char* request_name, - napi_value* result); NAPI_EXTERN napi_status napi_throw_jsvalue(napi_env env, napi_value error); -typedef enum { - NAPI_DIRECTION_INVALID = 0, - NAPI_DIRECTION_DYNAMIC_TO_STATIC = 1, // JS object references the STS object - NAPI_DIRECTION_STATIC_TO_DYNAMIC = 2, // STS object references the JS object - NAPI_DIRECTION_HYBRID = 3, // STS object and the JS object references each other -} NapiXRefDirection; -#ifdef PANDA_JS_ETS_HYBRID_MODE -// XGC specific internal API -NAPI_EXTERN napi_status napi_vm_handshake(napi_env env, void* inputIface, void** outputIface); -NAPI_EXTERN napi_status napi_xref_wrap(napi_env env, - napi_value js_object, - void* native_object, - napi_finalize finalize_cb, - NapiXRefDirection ref_direction, - napi_ref* result); -NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, void** result); - -NAPI_EXTERN napi_status napi_mark_from_object_for_cmc(napi_env env, napi_ref ref, - std::function &visitor); -NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref); -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); -NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env); -#endif // PANDA_JS_ETS_HYBRID_MODE 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_register_appstate_callback(napi_env env, NapiAppStateCallback callback); -NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, - const char* path, - const char* module_info, - napi_value* result, - bool isHybrid); -#endif /* FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_NODE_API_H */ +#endif /* FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_NODE_API_H */ \ No newline at end of file diff --git a/interfaces/inner_api/napi/native_node_hybrid_api.h b/interfaces/inner_api/napi/native_node_hybrid_api.h new file mode 100644 index 000000000..d77743382 --- /dev/null +++ b/interfaces/inner_api/napi/native_node_hybrid_api.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_NODE_HYBRID_API_H +#define FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_NODE_HYBRID_API_H + +#include +#include +#include +#include + +#include "js_native_api.h" +#include "native_common.h" +#include "node_api.h" + +typedef napi_value (*proxy_object_attach_cb)(napi_env env, void* data); + +typedef enum { + NAPI_APP_STATE_FOREGROUND = 0, + NAPI_APP_STATE_BACKGROUND = 1, + NAPI_APP_STATE_SENSITIVE_START = 2, + NAPI_APP_STATE_SENSITIVE_END = 3, + NAPI_APP_STATE_COLD_START_FINISHED = 4, + NAPI_APP_STATE_WARM_START = 5, +} NapiAppState; + +typedef enum { + NAPI_DIRECTION_INVALID = 0, + NAPI_DIRECTION_DYNAMIC_TO_STATIC = 1, // JS object references the STS object + NAPI_DIRECTION_STATIC_TO_DYNAMIC = 2, // STS object references the JS object + NAPI_DIRECTION_HYBRID = 3, // STS object and the JS object references each other +} NapiXRefDirection; + +typedef struct NapiStackInfo { + size_t stackStart; + size_t stackSize; +} NapiStackInfo; + +using NapiAppStateCallback = void (*)(int state, int64_t timestamp); + +NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, + const char* path, + const char* module_info, + napi_value* result); +NAPI_EXTERN napi_status napi_load_module_with_module_request(napi_env env, + const char* request_name, + napi_value* result); +NAPI_EXTERN napi_status napi_set_stackinfo(napi_env env, NapiStackInfo* napi_info); +NAPI_EXTERN napi_status napi_get_stackinfo(napi_env env, NapiStackInfo* result); +#ifdef PANDA_JS_ETS_HYBRID_MODE +// XGC specific internal API +NAPI_EXTERN napi_status napi_xref_wrap(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + NapiXRefDirection ref_direction, + napi_ref* result); + +NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, void** result); + +NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref); + +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_vm_handshake(napi_env env, void* inputIface, void** outputIface); + +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_mark_from_object_for_cmc(napi_env env, + napi_ref ref, + std::function& visitor); + +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_deserialize_hybrid(napi_env env, void* buffer, napi_value* object); +NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env); +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_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); +#endif // PANDA_JS_ETS_HYBRID_MODE +NAPI_EXTERN napi_status napi_register_appstate_callback(napi_env env, NapiAppStateCallback callback); + +#endif /* FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_NODE_HYBRID_API_H */ \ No newline at end of file diff --git a/napi.gni b/napi.gni index 2872c4dcb..83baf2841 100755 --- a/napi.gni +++ b/napi.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -33,6 +33,7 @@ napi_sources = [ "native_engine/native_engine.cpp", "native_engine/native_event.cpp", "native_engine/native_node_api.cpp", + "native_engine/native_node_hybrid_api.cpp", "native_engine/native_safe_async_work.cpp", "native_engine/native_sendable.cpp", "native_engine/worker_manager.cpp", diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp index 8408b9c05..96ee1b47d 100644 --- a/native_engine/native_api.cpp +++ b/native_engine/native_api.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -59,7 +59,6 @@ using panda::ecmascript::EcmaVM; static constexpr size_t MAX_BYTE_LENGTH = 2097152; static constexpr size_t ONEMIB_BYTE_SIZE = 1048576; static constexpr size_t SMALL_STRING_SIZE = 16; -static constexpr char NAME_SPACE_TAG = '@'; class HandleScopeWrapper { public: @@ -1980,57 +1979,6 @@ NAPI_EXTERN napi_status napi_wrap_enhance(napi_env env, return GET_RETURN_STATUS(env); } -NAPI_EXTERN napi_status napi_xref_wrap(napi_env env, - napi_value js_object, - void* native_object, - napi_finalize finalize_cb, - NapiXRefDirection ref_direction, - napi_ref* result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, js_object); - CHECK_ARG(env, native_object); - CHECK_ARG(env, finalize_cb); - - auto nativeValue = LocalValueFromJsValue(js_object); - auto callback = reinterpret_cast(finalize_cb); - 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; - auto reference = reinterpret_cast(result); - Local key = panda::StringRef::GetProxyNapiWrapperString(vm); - NativeReference* ref = nullptr; - Local object = JSValueRef::Undefined(vm); - switch (ref_direction) { - case NapiXRefDirection::NAPI_DIRECTION_DYNAMIC_TO_STATIC: - object = panda::ObjectRef::NewJSXRefObject(vm); - ref = engine->CreateXRefReference(js_object, 1, false, callback, native_object); - break; - case NapiXRefDirection::NAPI_DIRECTION_STATIC_TO_DYNAMIC: - object = panda::ObjectRef::New(vm); - ref = engine->CreateXRefReference(js_object, 1, false, callback, native_object); - break; - case NapiXRefDirection::NAPI_DIRECTION_HYBRID: - // Hybrid object may only exist in cross-language inherence case. - // To be aborted in the future according to the specification - HILOG_ERROR("[napi_xref_wrap] napi_direction_hybrid is not supported now!"); - return napi_set_last_error(env, napi_invalid_arg); - default: - HILOG_ERROR("[napi_xref_wrap] invalid ref_direction!"); - return napi_set_last_error(env, napi_invalid_arg); - } - if (reference != nullptr) { - *reference = ref; - } - object->SetNativePointerFieldCount(vm, 1); - object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize); - PropertyAttribute attr(object, true, false, true); - nativeObject->DefineProperty(vm, key, attr); - return GET_RETURN_STATUS(env); -} - // Ensure thread safety! Async finalizer will be called on the async thread. NAPI_EXTERN napi_status napi_wrap_async_finalizer(napi_env env, napi_value js_object, @@ -2135,28 +2083,6 @@ NAPI_EXTERN napi_status napi_unwrap(napi_env env, napi_value js_object, void** r return GET_RETURN_STATUS(env); } -NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, void** result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, js_object); - CHECK_ARG(env, result); - - auto nativeValue = LocalValueFromJsValue(js_object); - auto vm = reinterpret_cast(env)->GetEcmaVm(); - panda::JsiFastNativeScope fastNativeScope(vm); - CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject); - Local key = panda::StringRef::GetProxyNapiWrapperString(vm); - Local val = nativeObject->Get(vm, key); - *result = nullptr; - if (val->IsObject(vm)) { - Local ext(val); - auto ref = reinterpret_cast(ext->GetNativePointerField(vm, 0)); - *result = ref != nullptr ? ref->GetData() : nullptr; - } - - return GET_RETURN_STATUS(env); -} - NAPI_EXTERN napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result) { NAPI_PREAMBLE(env); @@ -3292,17 +3218,6 @@ NAPI_EXTERN napi_status napi_load_module_with_info(napi_env env, return GET_RETURN_STATUS(env); } -NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, - const char* path, - const char* module_info, - napi_value* result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, result); - auto engine = reinterpret_cast(env); - *result = engine->NapiLoadModuleWithInfoForHybridApp(path, module_info); - return GET_RETURN_STATUS(env); -} // Memory management NAPI_INNER_EXTERN napi_status napi_adjust_external_memory( napi_env env, int64_t change_in_bytes, int64_t* adjusted_value) @@ -4544,27 +4459,6 @@ NAPI_EXTERN napi_status napi_add_cleanup_finalizer(napi_env env, void (*fun)(voi return napi_clear_last_error(env); } -NAPI_EXTERN napi_status napi_set_stackinfo(napi_env env, napi_stack_info* napi_info) -{ - CHECK_ARG(env, napi_info); - ASSERT(napi_info != nullptr); - panda::StackInfo info { napi_info->stack_start, napi_info->stack_size }; - auto vm = reinterpret_cast(env)->GetEcmaVm(); - panda::JSNApi::SetStackInfo(vm, info); - return napi_clear_last_error(env); -} - -NAPI_EXTERN napi_status napi_get_stackinfo(napi_env env, napi_stack_info* result) -{ - CHECK_ARG(env, result); - ASSERT(result != nullptr); - auto vm = reinterpret_cast(env)->GetEcmaVm(); - auto res = panda::JSNApi::GetStackInfo(vm); - result->stack_start = res.stackStart; - result->stack_size = res.stackSize; - return napi_clear_last_error(env); -} - NAPI_EXTERN napi_status napi_throw_jsvalue(napi_env env, napi_value error) { CHECK_ENV(env); @@ -4594,34 +4488,6 @@ NAPI_EXTERN napi_status napi_load_module_with_path(napi_env env, const char* pat return GET_RETURN_STATUS(env); } -NAPI_EXTERN napi_status napi_load_module_with_module_request(napi_env env, const char* request_name, napi_value* result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, request_name); - CHECK_ARG(env, result); - - if (request_name[0] == NAME_SPACE_TAG) { - // load module with OhmUrl - auto [path, module_info] = panda::JSNApi::ResolveOhmUrl(request_name); - napi_load_module_with_info_hybrid(env, path.c_str(), module_info.c_str(), result); - } else { - napi_load_module_with_path(env, request_name, result); - } - - return GET_RETURN_STATUS(env); -} - -NAPI_EXTERN napi_status napi_register_appstate_callback(napi_env env, NapiAppStateCallback callback) -{ - CHECK_ENV(env); - CHECK_ARG(env, callback); - - auto* engine = reinterpret_cast(env); - engine->RegisterAppStateCallback(callback); - - return napi_clear_last_error(env); -} - NAPI_EXTERN napi_status napi_remove_cleanup_finalizer(napi_env env, void (*fun)(void* arg), void* arg) { CHECK_ENV(env); @@ -4715,134 +4581,3 @@ NAPI_EXTERN napi_status napi_destroy_ark_context(napi_env env) } return napi_ok; } - -#ifdef PANDA_JS_ETS_HYBRID_MODE -NAPI_EXTERN napi_status napi_vm_handshake(napi_env env, - [[maybe_unused]] void* inputIface, - [[maybe_unused]] void** outputIface) -{ - CHECK_ENV(env); - CHECK_ARG(env, inputIface); - CHECK_ARG(env, outputIface); - - auto vm = reinterpret_cast(env)->GetEcmaVm(); - panda::HandshakeHelper::DoHandshake(const_cast(vm), inputIface, outputIface); - - return napi_clear_last_error(env); -} - -NAPI_EXTERN napi_status napi_mark_from_object_for_cmc(napi_env env, napi_ref ref, - std::function &visitor) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, ref); - ArkNativeReference* reference = reinterpret_cast(ref); - reference->MarkFromObject(visitor); - return napi_clear_last_error(env); -} - -NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, ref); - ArkNativeReference* reference = reinterpret_cast(ref); - reference->MarkFromObject(); - return napi_clear_last_error(env); -} - -NAPI_EXTERN napi_status napi_is_alive_object(napi_env env, napi_ref ref, bool* result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, ref); - ArkNativeReference* reference = reinterpret_cast(ref); - *result = reference->IsObjectAlive(); - return napi_clear_last_error(env); -} - -NAPI_EXTERN napi_status napi_is_contain_object(napi_env env, napi_ref ref, bool* result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, ref); - ArkNativeReference* reference = reinterpret_cast(ref); - *result = reference->IsValidHeapObject(); - return napi_clear_last_error(env); -} - -NAPI_EXTERN napi_status napi_create_xref(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref* result) -{ - CHECK_ENV(env); - CHECK_ARG(env, value); - CHECK_ARG(env, result); - - auto engine = reinterpret_cast(env); - auto ref = engine->CreateXRefReference(value, initial_refcount, false, nullptr, nullptr); - *result = reinterpret_cast(ref); - return napi_clear_last_error(env); -} - -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); - CHECK_ARG(env, js_object); - CHECK_ARG(env, native_object); - CHECK_ARG(env, finalize_cb); - CHECK_ARG(env, result); - - auto nativeValue = LocalValueFromJsValue(js_object); - auto callback = reinterpret_cast(finalize_cb); - 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; - auto reference = reinterpret_cast(result); - Local key = panda::StringRef::GetProxyNapiWrapperString(vm); - NativeReference* ref = nullptr; - Local object = panda::ObjectRef::NewJSXRefObject(vm); - // 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, - [](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); -} - -NAPI_EXTERN napi_status napi_is_xref_type(napi_env env, napi_value js_object, bool* result) -{ - *result = false; - NAPI_PREAMBLE(env); - CHECK_ARG(env, js_object); - CHECK_ARG(env, result); - - 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); - Local key = panda::StringRef::GetProxyNapiWrapperString(vm); - - if (nativeObject->Has(vm, key)) { - *result = true; - } - return GET_RETURN_STATUS(env); -} -#endif // PANDA_JS_ETS_HYBRID_MODE diff --git a/native_engine/native_engine.h b/native_engine/native_engine.h index 54ab66e3d..2a1925c7b 100644 --- a/native_engine/native_engine.h +++ b/native_engine/native_engine.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -29,6 +29,7 @@ #include "callback_scope_manager/native_callback_scope_manager.h" #include "ecmascript/napi/include/jsnapi.h" #include "module_manager/native_module_manager.h" +#include "napi/native_node_hybrid_api.h" #include "native_engine/native_async_work.h" #include "native_engine/native_deferred.h" #include "native_engine/native_reference.h" diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index 60de7ea63..d9ca449d8 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -17,11 +17,6 @@ #include "native_engine/native_async_hook_context.h" #include "native_engine/native_utils.h" #include "native_engine/impl/ark/ark_native_engine.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; @@ -649,105 +644,4 @@ NAPI_EXTERN napi_status napi_set_module_validate_callback(napi_module_validate_c return napi_ok; } return napi_generic_failure; -} -NAPI_EXTERN napi_status napi_get_ets_implements(napi_env env, napi_value value, napi_value* result) -{ - NAPI_PREAMBLE(env); - CHECK_ARG(env, value); - CHECK_ARG(env, result); - - auto nativeValue = LocalValueFromJsValue(value); - auto engine = reinterpret_cast(env); - auto vm = engine->GetEcmaVm(); - Local implementsValue = panda::JSNApi::GetImplements(vm, nativeValue); - *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); - panda::PropertyAttribute attr(object, true, false, true); - nativeObject->DefineProperty(vm, key, attr); - return GET_RETURN_STATUS(env); -} - -NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env) -{ - NAPI_PREAMBLE(env); - - auto engine = reinterpret_cast(env); - auto vm = engine->GetEcmaVm(); - panda::JSNApi::InitHybridVMEnv(vm); - return GET_RETURN_STATUS(env); -} -#endif // PANDA_JS_ETS_HYBRID_MODE \ No newline at end of file +} \ No newline at end of file diff --git a/native_engine/native_node_hybrid_api.cpp b/native_engine/native_node_hybrid_api.cpp new file mode 100644 index 000000000..dd4a43ec1 --- /dev/null +++ b/native_engine/native_node_hybrid_api.cpp @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef NAPI_EXPERIMENTAL +#define NAPI_EXPERIMENTAL +#endif + +#ifdef ENABLE_CONTAINER_SCOPE +#include "core/common/container_scope.h" +#endif + +#include "ecmascript/napi/include/jsnapi.h" +#include "ecmascript/napi/include/jsnapi_expo.h" +#include "native_api_internal.h" +#include "native_engine/impl/ark/ark_native_reference.h" +#include "native_engine/native_create_env.h" +#include "native_engine/native_utils.h" +#include "native_engine/worker_manager.h" +#include "securec.h" + +using panda::ObjectRef; +static constexpr char NAME_SPACE_TAG = '@'; +NAPI_EXTERN napi_status napi_load_module_with_info_hybrid(napi_env env, + const char* path, + const char* module_info, + napi_value* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, result); + auto engine = reinterpret_cast(env); + *result = engine->NapiLoadModuleWithInfoForHybridApp(path, module_info); + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_load_module_with_module_request(napi_env env, const char* request_name, napi_value* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, request_name); + CHECK_ARG(env, result); + + if (request_name[0] == NAME_SPACE_TAG) { + // load module with OhmUrl + auto [path, module_info] = panda::JSNApi::ResolveOhmUrl(request_name); + napi_load_module_with_info_hybrid(env, path.c_str(), module_info.c_str(), result); + } else { + napi_load_module_with_path(env, request_name, result); + } + + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_set_stackinfo(napi_env env, NapiStackInfo* napi_info) +{ + CHECK_ARG(env, napi_info); + ASSERT(napi_info != nullptr); + panda::StackInfo info { napi_info->stackStart, napi_info->stackSize }; + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::JSNApi::SetStackInfo(vm, info); + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_get_stackinfo(napi_env env, NapiStackInfo* result) +{ + CHECK_ARG(env, result); + ASSERT(result != nullptr); + auto vm = reinterpret_cast(env)->GetEcmaVm(); + auto res = panda::JSNApi::GetStackInfo(vm); + result->stackStart = res.stackStart; + result->stackSize = res.stackSize; + return napi_clear_last_error(env); +} + +#ifdef PANDA_JS_ETS_HYBRID_MODE +NAPI_EXTERN napi_status napi_xref_wrap(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + NapiXRefDirection ref_direction, + napi_ref* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, js_object); + CHECK_ARG(env, native_object); + CHECK_ARG(env, finalize_cb); + + auto nativeValue = LocalValueFromJsValue(js_object); + auto callback = reinterpret_cast(finalize_cb); + 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; + auto reference = reinterpret_cast(result); + Local key = panda::StringRef::GetProxyNapiWrapperString(vm); + NativeReference* ref = nullptr; + Local object = JSValueRef::Undefined(vm); + switch (ref_direction) { + case NapiXRefDirection::NAPI_DIRECTION_DYNAMIC_TO_STATIC: + object = panda::ObjectRef::NewJSXRefObject(vm); + ref = engine->CreateXRefReference(js_object, 1, false, callback, native_object); + break; + case NapiXRefDirection::NAPI_DIRECTION_STATIC_TO_DYNAMIC: + object = panda::ObjectRef::New(vm); + ref = engine->CreateXRefReference(js_object, 1, false, callback, native_object); + break; + case NapiXRefDirection::NAPI_DIRECTION_HYBRID: + // Hybrid object may only exist in cross-language inherence case. + // To be aborted in the future according to the specification + HILOG_ERROR("[napi_xref_wrap] napi_direction_hybrid is not supported now!"); + return napi_set_last_error(env, napi_invalid_arg); + default: + HILOG_ERROR("[napi_xref_wrap] invalid ref_direction!"); + return napi_set_last_error(env, napi_invalid_arg); + } + if (reference != nullptr) { + *reference = ref; + } + object->SetNativePointerFieldCount(vm, 1); + object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize); + panda::PropertyAttribute attr(object, true, false, true); + nativeObject->DefineProperty(vm, key, attr); + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, void** result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, js_object); + CHECK_ARG(env, result); + + auto nativeValue = LocalValueFromJsValue(js_object); + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::JsiFastNativeScope fastNativeScope(vm); + CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject); + Local key = panda::StringRef::GetProxyNapiWrapperString(vm); + Local val = nativeObject->Get(vm, key); + *result = nullptr; + if (val->IsObject(vm)) { + Local ext(val); + auto ref = reinterpret_cast(ext->GetNativePointerField(vm, 0)); + *result = ref != nullptr ? ref->GetData() : nullptr; + } + + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_mark_from_object(napi_env env, napi_ref ref) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, ref); + ArkNativeReference* reference = reinterpret_cast(ref); + reference->MarkFromObject(); + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_create_xref(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref* result) +{ + CHECK_ENV(env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); + + auto engine = reinterpret_cast(env); + auto ref = engine->CreateXRefReference(value, initial_refcount, false, nullptr, nullptr); + *result = reinterpret_cast(ref); + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_get_ets_implements(napi_env env, napi_value value, napi_value* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); + + auto nativeValue = LocalValueFromJsValue(value); + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + Local implementsValue = panda::JSNApi::GetImplements(vm, nativeValue); + *result = JsValueFromLocalValue(implementsValue); + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_register_appstate_callback(napi_env env, NapiAppStateCallback callback) +{ + CHECK_ENV(env); + CHECK_ARG(env, callback); + + auto* engine = reinterpret_cast(env); + engine->RegisterAppStateCallback(callback); + + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_vm_handshake(napi_env env, + [[maybe_unused]] void* inputIface, + [[maybe_unused]] void** outputIface) +{ + CHECK_ENV(env); + CHECK_ARG(env, inputIface); + CHECK_ARG(env, outputIface); + + auto vm = reinterpret_cast(env)->GetEcmaVm(); + panda::HandshakeHelper::DoHandshake(const_cast(vm), inputIface, outputIface); + + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_mark_from_object_for_cmc(napi_env env, + napi_ref ref, + std::function& visitor) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, ref); + ArkNativeReference* reference = reinterpret_cast(ref); + reference->MarkFromObject(visitor); + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_is_alive_object(napi_env env, napi_ref ref, bool* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, ref); + ArkNativeReference* reference = reinterpret_cast(ref); + *result = reference->IsObjectAlive(); + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_is_contain_object(napi_env env, napi_ref ref, bool* result) +{ + NAPI_PREAMBLE(env); + CHECK_ARG(env, ref); + ArkNativeReference* reference = reinterpret_cast(ref); + *result = reference->IsValidHeapObject(); + return napi_clear_last_error(env); +} + +NAPI_EXTERN napi_status napi_is_xref_type(napi_env env, napi_value js_object, bool* result) +{ + *result = false; + NAPI_PREAMBLE(env); + CHECK_ARG(env, js_object); + CHECK_ARG(env, result); + + auto nativeValue = LocalValueFromJsValue(js_object); + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject); + Local key = panda::StringRef::GetProxyNapiWrapperString(vm); + + if (nativeObject->Has(vm, key)) { + *result = true; + } + return GET_RETURN_STATUS(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); + panda::PropertyAttribute attr(object, true, false, true); + nativeObject->DefineProperty(vm, key, attr); + return GET_RETURN_STATUS(env); +} + +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_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); + CHECK_ARG(env, js_object); + CHECK_ARG(env, native_object); + CHECK_ARG(env, finalize_cb); + CHECK_ARG(env, result); + + auto nativeValue = LocalValueFromJsValue(js_object); + auto callback = reinterpret_cast(finalize_cb); + 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; + auto reference = reinterpret_cast(result); + Local key = panda::StringRef::GetProxyNapiWrapperString(vm); + NativeReference* ref = nullptr; + Local object = panda::ObjectRef::NewJSXRefObject(vm); + // 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, + [](void* env, void* data, void* info) { + panda::JSNApi::XRefBindingInfo* externalInfo = reinterpret_cast(info); + delete externalInfo; + }, + reinterpret_cast(data), nativeBindingSize); + panda::PropertyAttribute attr(object, true, false, true); + nativeObject->DefineProperty(vm, key, attr); + return GET_RETURN_STATUS(env); +} + +NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env) +{ + NAPI_PREAMBLE(env); + + auto engine = reinterpret_cast(env); + auto vm = engine->GetEcmaVm(); + panda::JSNApi::InitHybridVMEnv(vm); + return GET_RETURN_STATUS(env); +} +#endif // PANDA_JS_ETS_HYBRID_MODE diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index 142a6439a..703f50101 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -28,6 +28,7 @@ #include "ecmascript/napi/include/jsnapi_expo.h" #include "napi/native_common.h" #include "napi/native_node_api.h" +#include "napi/native_node_hybrid_api.h" #include "native_create_env.h" #include "native_utils.h" #include "reference_manager/native_reference_manager.h" -- Gitee From 329411ae2e5b0268a66c74a21fde0c48f54be047 Mon Sep 17 00:00:00 2001 From: lhc Date: Mon, 21 Jul 2025 22:44:33 +0800 Subject: [PATCH 14/17] Isolate the code of interop Issue: https://gitee.com/open_harmony/dashboard?issue_id=ICNFMT Signed-off-by: lhc Change-Id: Iab0b0991cbe1eb8d2b8f4f87018a51586c25cb12 --- napi.gni | 5 ++ native_engine/impl/ark/ark_native_engine.cpp | 5 +- .../impl/ark/ark_native_reference.cpp | 36 ++-------- native_engine/impl/ark/ark_native_reference.h | 32 +++++---- .../impl/ark/ark_xref_native_reference.cpp | 67 +++++++++++++++++++ .../impl/ark/ark_xref_native_reference.h | 34 ++++++++++ native_engine/native_node_api.cpp | 3 +- 7 files changed, 136 insertions(+), 46 deletions(-) create mode 100644 native_engine/impl/ark/ark_xref_native_reference.cpp create mode 100644 native_engine/impl/ark/ark_xref_native_reference.h diff --git a/napi.gni b/napi.gni index 2872c4dcb..6778828f9 100755 --- a/napi.gni +++ b/napi.gni @@ -41,6 +41,11 @@ napi_sources = [ "utils/log.cpp", ] +# supported for hybrid +napi_sources += [ + "native_engine/impl/ark/ark_xref_native_reference.cpp", +] + if (is_mingw) { napi_sources += [ "utils/platform/windows/file.cpp" ] } else { diff --git a/native_engine/impl/ark/ark_native_engine.cpp b/native_engine/impl/ark/ark_native_engine.cpp index 4715f4eb9..51d39d2e0 100644 --- a/native_engine/impl/ark/ark_native_engine.cpp +++ b/native_engine/impl/ark/ark_native_engine.cpp @@ -22,6 +22,7 @@ #include "ark_native_deferred.h" #include "ark_native_reference.h" +#include "ark_xref_native_reference.h" #include "ark_native_timer.h" #include "native_engine/native_utils.h" #include "native_sendable.h" @@ -1979,8 +1980,8 @@ NativeReference* ArkNativeEngine::CreateReference(napi_value value, uint32_t ini NativeReference* ArkNativeEngine::CreateXRefReference(napi_value value, uint32_t initialRefcount, bool flag, NapiNativeFinalize callback, void* data) { - ArkNativeReferenceConfig config(initialRefcount, true, flag, callback, data); - return new ArkNativeReference(this, value, config); + ArkNativeReferenceConfig config(initialRefcount, flag, callback, data); + return new ArkXRefNativeReference(this, value, config); } NativeReference* ArkNativeEngine::CreateAsyncReference(napi_value value, uint32_t initialRefcount, diff --git a/native_engine/impl/ark/ark_native_reference.cpp b/native_engine/impl/ark/ark_native_reference.cpp index 706dfea2b..2d990f858 100644 --- a/native_engine/impl/ark/ark_native_reference.cpp +++ b/native_engine/impl/ark/ark_native_reference.cpp @@ -39,23 +39,7 @@ ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, nativeBindingSize_(nativeBindingSize) { InitProperties(deleteSelf, isAsyncCall); - ArkNativeReferenceConstructor(); -} - -ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, - napi_value value, - ArkNativeReferenceConfig& config) - : engine_(engine), - value_(), - refCount_(config.initialRefcount), - ownership_(config.deleteSelf ? ReferenceOwnerShip::RUNTIME : ReferenceOwnerShip::USER), - isProxyReference_(config.isProxyReference), - napiCallback_(config.napiCallback), - data_(config.data) -{ - InitProperties(config.deleteSelf, false); - value_.CreateXRefGloablReference(engine->GetEcmaVm(), LocalValueFromJsValue(value)); - ArkNativeReferenceConstructor(); + ArkNativeReferenceConstructor(FreeGlobalCallBack); } ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, @@ -77,10 +61,10 @@ ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, nativeBindingSize_(nativeBindingSize) { InitProperties(deleteSelf, isAsyncCall); - ArkNativeReferenceConstructor(); + ArkNativeReferenceConstructor(FreeGlobalCallBack); } -void ArkNativeReference::ArkNativeReferenceConstructor() +void ArkNativeReference::ArkNativeReferenceConstructor(WeakRefClearCallBack weakCallback) { if (napiCallback_ != nullptr) { // Async callback will redirect to root engine, no monitoring needed. @@ -96,7 +80,7 @@ void ArkNativeReference::ArkNativeReferenceConstructor() } if (refCount_ == 0) { - value_.SetWeakCallback(reinterpret_cast(this), FreeGlobalCallBack, NativeFinalizeCallBack); + value_.SetWeakCallback(reinterpret_cast(this), weakCallback, NativeFinalizeCallBack); } if (ownership_ == ReferenceOwnerShip::RUNTIME) { @@ -140,11 +124,7 @@ ArkNativeReference::~ArkNativeReference() return; } SetHasDelete(); - if (isProxyReference_) { - value_.FreeXRefGlobalHandleAddr(); - } else { - value_.FreeGlobalHandleAddr(); - } + value_.FreeGlobalHandleAddr(); FinalizeCallback(FinalizerState::DESTRUCTION); } @@ -292,11 +272,7 @@ void ArkNativeReference::FinalizeCallback(FinalizerState state) void ArkNativeReference::FreeGlobalCallBack(void* ref) { auto that = reinterpret_cast(ref); - if (that->isProxyReference_) { - that->value_.FreeXRefGlobalHandleAddr(); - } else { - that->value_.FreeGlobalHandleAddr(); - } + that->value_.FreeGlobalHandleAddr(); } void ArkNativeReference::NativeFinalizeCallBack(void* ref) diff --git a/native_engine/impl/ark/ark_native_reference.h b/native_engine/impl/ark/ark_native_reference.h index 9ead72981..27e4e4913 100644 --- a/native_engine/impl/ark/ark_native_reference.h +++ b/native_engine/impl/ark/ark_native_reference.h @@ -41,23 +41,23 @@ enum class ReferenceOwnerShip : uint8_t { struct ArkNativeReferenceConfig { uint32_t initialRefcount; - bool isProxyReference; bool deleteSelf; NapiNativeFinalize napiCallback; void* data; - ArkNativeReferenceConfig(uint32_t initialRefcount, - bool isProxyReference, + explicit ArkNativeReferenceConfig(uint32_t initialRefcount, bool deleteSelf = false, NapiNativeFinalize napiCallback = nullptr, void* data = nullptr) : initialRefcount(initialRefcount), - isProxyReference(isProxyReference), deleteSelf(deleteSelf), napiCallback(napiCallback), - data(data) {} + data(data) + {} }; +using WeakRefClearCallBack = void (*)(void*); + class ArkNativeReference : public NativeReference { public: ArkNativeReference(ArkNativeEngine* engine, @@ -69,9 +69,6 @@ public: void* hint = nullptr, bool isAsyncCall = false, size_t nativeBindingSize = 0); - ArkNativeReference(ArkNativeEngine* engine, - napi_value value, - ArkNativeReferenceConfig &config); ArkNativeReference(ArkNativeEngine* engine, Local value, uint32_t initialRefcount, @@ -102,7 +99,19 @@ public: bool IsValidHeapObject(); #endif // PANDA_JS_ETS_HYBRID_MODE -private: +protected: + ArkNativeReference(ArkNativeEngine* engine, + const ArkNativeReferenceConfig &config) + : engine_(engine), + value_(), + refCount_(config.initialRefcount), + ownership_(config.deleteSelf ? ReferenceOwnerShip::RUNTIME : ReferenceOwnerShip::USER), + napiCallback_(config.napiCallback), + data_(config.data) + {} + + void ArkNativeReferenceConstructor(WeakRefClearCallBack weakCallback); + enum ReferencePropertiesMask : uint8_t { DELETE_SELF_MASK = 1, IS_ASYNC_CALL_MASK = DELETE_SELF_MASK << 1, @@ -110,7 +119,6 @@ private: FINAL_RAN_MASK = HAS_DELETE_MASK << 1, }; - void ArkNativeReferenceConstructor(); void InitProperties(bool deleteSelf = false, bool isAsyncCall = false); ArkNativeEngine* engine_; @@ -123,7 +131,6 @@ private: // Bit-packed flags: saves memory and speeds up object creation vs. multiple bools. // std::bitset will use more memory than uint8_t number. uint8_t properties_ {0}; - bool isProxyReference_{false}; NapiNativeFinalize napiCallback_ {nullptr}; void* data_ {nullptr}; @@ -146,8 +153,9 @@ private: void IncreaseCounter(); void DecreaseCounter(); - static void FreeGlobalCallBack(void* ref); static void NativeFinalizeCallBack(void* ref); +private: + static void FreeGlobalCallBack(void* ref); friend class NativeReferenceManager; }; diff --git a/native_engine/impl/ark/ark_xref_native_reference.cpp b/native_engine/impl/ark/ark_xref_native_reference.cpp new file mode 100644 index 000000000..32dc0a58d --- /dev/null +++ b/native_engine/impl/ark/ark_xref_native_reference.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ark_xref_native_reference.h" +#include + +#include "native_engine/native_api_internal.h" +#include "native_engine/native_utils.h" + +ArkXRefNativeReference::ArkXRefNativeReference(ArkNativeEngine* engine, + napi_value value, + const ArkNativeReferenceConfig &config) + : ArkNativeReference(engine, config) +{ + value_.CreateXRefGloablReference(engine->GetEcmaVm(), LocalValueFromJsValue(value)); + ArkNativeReferenceConstructor(FreeXRefGlobalCallBack); +} + +ArkXRefNativeReference::~ArkXRefNativeReference() +{ + VALID_ENGINE_CHECK(engine_, engine_, engineId_); + + if (engine_->GetReferenceManager()) { + engine_->GetReferenceManager()->ReleaseHandler(this); + prev_ = nullptr; + next_ = nullptr; + } + if (value_.IsEmpty()) { + return; + } + value_.FreeXRefGlobalHandleAddr(); + FinalizeCallback(FinalizerState::DESTRUCTION); +} + +void ArkXRefNativeReference::FreeXRefGlobalCallBack(void* ref) +{ + auto that = reinterpret_cast(ref); + that->value_.FreeXRefGlobalHandleAddr(); +} + +uint32_t ArkXRefNativeReference::Unref() +{ + if (refCount_ == 0) { + return refCount_; + } + --refCount_; + if (value_.IsEmpty()) { + return refCount_; + } + if (refCount_ == 0) { + value_.SetWeakCallback(reinterpret_cast(this), FreeXRefGlobalCallBack, NativeFinalizeCallBack); + } + return refCount_; +} + \ No newline at end of file diff --git a/native_engine/impl/ark/ark_xref_native_reference.h b/native_engine/impl/ark/ark_xref_native_reference.h new file mode 100644 index 000000000..949ffa417 --- /dev/null +++ b/native_engine/impl/ark/ark_xref_native_reference.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_XREF_REFERENCE_H +#define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_XREF_REFERENCE_H + +#include "native_engine/impl/ark/ark_native_reference.h" + +class ArkXRefNativeReference : public ArkNativeReference { +public: + ArkXRefNativeReference(ArkNativeEngine* engine, + napi_value value, + const ArkNativeReferenceConfig &config); + ~ArkXRefNativeReference() override; + uint32_t Unref() override; + +private: + static void FreeXRefGlobalCallBack(void* ref); +}; + +#endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_XREF_REFERENCE_H */ + \ No newline at end of file diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index 60de7ea63..bd1943bf5 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -368,7 +368,6 @@ NAPI_EXTERN napi_status napi_create_threadsafe_function(napi_env env, napi_value { CHECK_ENV(env); CHECK_ARG(env, async_resource_name); - RETURN_STATUS_IF_FALSE(env, max_queue_size >= 0, napi_invalid_arg); RETURN_STATUS_IF_FALSE( env, initial_thread_count > 0 && initial_thread_count <= MAX_THREAD_SAFE_COUNT, napi_invalid_arg); CHECK_ARG(env, result); @@ -747,7 +746,7 @@ NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env) auto engine = reinterpret_cast(env); auto vm = engine->GetEcmaVm(); - panda::JSNApi::InitHybridVMEnv(vm); + panda::JSNApi::InitHybridVMEnv(const_cast(vm)); return GET_RETURN_STATUS(env); } #endif // PANDA_JS_ETS_HYBRID_MODE \ No newline at end of file -- Gitee From 0e2af81cd3fdcf0d2b508dd6dadd5fc1a7007da8 Mon Sep 17 00:00:00 2001 From: jiangmingcheng Date: Wed, 30 Jul 2025 12:01:09 +0800 Subject: [PATCH 15/17] Cherry-pick!2316 Remove redundantly declared interfaces Issue: https://gitee.com/openharmony/arkui_napi/issues/ICQALG Signed-off-by: jiangmingcheng Change-Id: Ifef1c74cd5a733385f8bf91fccc8c6c54567ea38 --- interfaces/inner_api/napi/native_node_api.h | 4 ---- native_engine/native_engine.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/interfaces/inner_api/napi/native_node_api.h b/interfaces/inner_api/napi/native_node_api.h index 699c910f4..78ca10ded 100644 --- a/interfaces/inner_api/napi/native_node_api.h +++ b/interfaces/inner_api/napi/native_node_api.h @@ -196,8 +196,4 @@ NAPI_EXTERN napi_status napi_load_module_with_path(napi_env env, const char* pat napi_value* result); NAPI_EXTERN napi_status napi_throw_jsvalue(napi_env env, napi_value error); -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); - #endif /* FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_NODE_API_H */ \ No newline at end of file diff --git a/native_engine/native_engine.h b/native_engine/native_engine.h index 2a1925c7b..5dc5d7477 100644 --- a/native_engine/native_engine.h +++ b/native_engine/native_engine.h @@ -28,8 +28,8 @@ #include "callback_scope_manager/native_callback_scope_manager.h" #include "ecmascript/napi/include/jsnapi.h" +#include "interfaces/inner_api/napi/native_node_hybrid_api.h" #include "module_manager/native_module_manager.h" -#include "napi/native_node_hybrid_api.h" #include "native_engine/native_async_work.h" #include "native_engine/native_deferred.h" #include "native_engine/native_reference.h" -- Gitee From d6249bb867a5e2b5938f47e4d5a19e457424fd4c Mon Sep 17 00:00:00 2001 From: jiangmingcheng Date: Mon, 4 Aug 2025 14:26:39 +0800 Subject: [PATCH 16/17] Cherry-pick! 2319 Remove duplicate test suites Issue: https://gitee.com/openharmony/arkui_napi/issues/ICQWM8 Signed-off-by: jiangmingcheng Change-Id: Ie59dae79f764f825b740b975a13c4fda73f1ce97 --- test/unittest/test_napi.cpp | 41 ------------------------------------- 1 file changed, 41 deletions(-) diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index 703f50101..8e0b35518 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -9098,47 +9098,6 @@ HWTEST_F(NapiBasicTest, NapiGetValueBigintInt64Test004, testing::ext::TestSize.L ASSERT_EQ(status, napi_bigint_expected); } -HWTEST_F(NapiBasicTest, NapiIsAliveObjectTest001, testing::ext::TestSize.Level1) -{ - napi_env env = reinterpret_cast(engine_); - napi_value obj; - napi_ref result = nullptr; - bool res = false; - - napi_create_object(env, &obj); - napi_status status = - 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); -} - -HWTEST_F(NapiBasicTest, NapiIsValidHeapObjectTest001, testing::ext::TestSize.Level1) -{ - napi_env env = reinterpret_cast(engine_); - napi_value obj; - napi_ref result = nullptr; - bool res = false; - - napi_create_object(env, &obj); - napi_status status = - 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); -} - -HWTEST_F(NapiBasicTest, NapiIsXrefTypeTest001, testing::ext::TestSize.Level1) -{ - napi_env env = reinterpret_cast(engine_); - napi_value obj; - bool res = false; - - napi_create_object(env, &obj); - napi_status status = napi_is_xref_type(env, obj, &res); - ASSERT_EQ(status, napi_ok); -} - HWTEST_F(NapiBasicTest, NapiGetValueBigintInt64Test005, testing::ext::TestSize.Level1) { napi_env env = reinterpret_cast(engine_); -- Gitee From 53d3352b717eac489b396aaf61218a7c30df95d5 Mon Sep 17 00:00:00 2001 From: MockMockBlack Date: Sat, 2 Aug 2025 20:48:41 +0800 Subject: [PATCH 17/17] [Interop] napi_xref_unwrap bugFix Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICPU5C Change-Id: I17b6b6aa7e336e09f26ca61604a657bd78251b6d Signed-off-by: MockMockBlack --- native_engine/native_node_hybrid_api.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/native_engine/native_node_hybrid_api.cpp b/native_engine/native_node_hybrid_api.cpp index 6ff464f1a..4bed014ce 100644 --- a/native_engine/native_node_hybrid_api.cpp +++ b/native_engine/native_node_hybrid_api.cpp @@ -144,7 +144,16 @@ NAPI_EXTERN napi_status napi_xref_unwrap(napi_env env, napi_value js_object, voi panda::JsiFastNativeScope fastNativeScope(vm); CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject); Local key = panda::StringRef::GetProxyNapiWrapperString(vm); - Local val = nativeObject->Get(vm, key); + + Local val = {}; + if (UNLIKELY(nativeValue->IsProxy(vm))) { + val = nativeObject->Get(vm, key); + } else { + panda::PropertyAttribute property; + nativeObject->GetOwnProperty(vm, key, property); + val = property.GetValue(vm); + } + *result = nullptr; if (val->IsObject(vm)) { Local ext(val); -- Gitee