• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "arkts_esvalue.h"
17 
18 #include <node_api.h>
19 
20 #include "plugins/ets/runtime/ani/scoped_objects_fix.h"
21 #include "plugins/ets/runtime/ets_napi_env.h"
22 #include "plugins/ets/runtime/interop_js/code_scopes.h"
23 #include "plugins/ets/runtime/interop_js/interop_context.h"
24 #include "plugins/ets/runtime/interop_js/js_convert.h"
25 
26 namespace ark::ets::interop::js {
27 
28 static ani_class g_esvalueClass {};
29 static ani_method g_isEcmaObjectMethod {};
30 static ani_field g_evField {};
31 
CacheEsValueClass(ani_env * env)32 static bool CacheEsValueClass(ani_env *env)
33 {
34     ani_class esvalueClass {};
35     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
36     [[maybe_unused]] auto status = env->FindClass("std.interop.ESValue", &esvalueClass);
37     ASSERT(status == ANI_OK);
38     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
39     if (UNLIKELY(env->GlobalReference_Create(esvalueClass, reinterpret_cast<ani_ref *>(&g_esvalueClass)) != ANI_OK)) {
40         return false;
41     }
42     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
43     status = env->Class_FindMethod(esvalueClass, "isECMAObject", ":z", &g_isEcmaObjectMethod);
44     ASSERT(status == ANI_OK);
45     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
46     status = env->Class_FindField(esvalueClass, "ev", &g_evField);
47     ASSERT(status == ANI_OK);
48     return true;
49 }
50 
InitializeGlobalOnce(ani_env * env)51 static bool InitializeGlobalOnce(ani_env *env)
52 {
53     // Guaranteed to be called once
54     static bool isInitialized = CacheEsValueClass(env);
55     return isInitialized;
56 }
57 
UnwrapESValue(ani_env * env,ani_object esvalue,void ** result)58 PANDA_PUBLIC_API bool UnwrapESValue(ani_env *env, ani_object esvalue, void **result)
59 {
60     if (UNLIKELY(!InitializeGlobalOnce(env))) {
61         return false;
62     }
63 
64     auto *coro = EtsCoroutine::GetCurrent();
65     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
66     if (UNLIKELY(PandaEtsNapiEnv::FromAniEnv(env)->GetEtsCoroutine() != coro)) {
67         return false;
68     }
69     auto ctx = InteropCtx::Current(coro);
70     if (ctx == nullptr) {
71         return false;
72     }
73 
74     ani_boolean isEsValue = ANI_FALSE;
75     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
76     [[maybe_unused]] auto status = env->Object_InstanceOf(esvalue, g_esvalueClass, &isEsValue);
77     if (status != ANI_OK || isEsValue == ANI_FALSE) {
78         return false;
79     }
80     ani_boolean isEcmaObject = ANI_FALSE;
81     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
82     status = env->Object_CallMethod_Boolean(esvalue, g_isEcmaObjectMethod, &isEcmaObject);
83     if (UNLIKELY(status != ANI_OK || isEcmaObject == ANI_FALSE)) {
84         return false;
85     }
86     ani_ref jsValue {};
87     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
88     status = env->Object_GetField_Ref(esvalue, g_evField, &jsValue);
89     ASSERT(status == ANI_OK);
90 
91     ani::ScopedManagedCodeFix s(env);
92     auto *jsValueObject = JSValue::FromEtsObject(s.ToInternalType(jsValue));
93 
94     INTEROP_CODE_SCOPE_ETS(coro);
95     auto jsenv = ctx->GetJSEnv();
96     NapiScope jsHandleScope(jsenv);
97 
98     auto jsObj = JSConvertJSValue::WrapWithNullCheck(jsenv, jsValueObject);
99     void *res = nullptr;
100     if (napi_unwrap(jsenv, jsObj, &res) != napi_ok) {
101         return false;
102     }
103     *result = res;
104     return true;
105 }
106 }  // namespace ark::ets::interop::js