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_entry_loader.h"
17
18 #include "base/log/log_wrapper.h"
19 #include "bridge/arkts_frontend/arkts_ani_utils.h"
20 #include "core/common/container.h"
21
22 namespace OHOS::Ace {
23
24 static const std::string ENTRY_PREFIX = "/src/main/ets/";
25 static const std::string ENTRY_SUFFIX = "/__EntryWrapper";
26
GetPageEntryObj()27 ani_object EntryLoader::GetPageEntryObj()
28 {
29 auto container = Container::Current();
30 if (!container) {
31 LOGE("EntryLoader GetPageEntryObj failed, container is null");
32 return nullptr;
33 }
34 const std::string moduleName = container->GetModuleName();
35 std::string entryPointName;
36 entryPointName.reserve(moduleName.size() + ENTRY_PREFIX.size() + url_.size() + ENTRY_SUFFIX.size());
37 entryPointName.append(moduleName).append(ENTRY_PREFIX).append(url_).append(ENTRY_SUFFIX);
38 ani_string entryStr;
39 env_->String_NewUTF8(entryPointName.c_str(), entryPointName.length(), &entryStr);
40 ani_class entryClass = nullptr;
41 ani_ref entryClassRef = nullptr;
42 ani_class cls = nullptr;
43 ani_status state;
44 ani_ref linkerRef;
45
46 do {
47 if ((state = static_cast<ani_status>(ArktsAniUtils::GetNearestNonBootRuntimeLinker(env_, linkerRef))) !=
48 ANI_OK) {
49 LOGE("EntryLoader Get getNearestNonBootRuntimeLinker failed, %{public}d", state);
50 break;
51 }
52 if ((state = env_->FindClass("Lstd/core/RuntimeLinker;", &cls)) != ANI_OK) {
53 LOGE("EntryLoader FindClass RuntimeLinker failed, %{public}d", state);
54 break;
55 }
56
57 ani_method loadClassMethod;
58 if ((state = env_->Class_FindMethod(cls, "loadClass", "Lstd/core/String;Lstd/core/Boolean;:Lstd/core/Class;",
59 &loadClassMethod)) != ANI_OK) {
60 LOGE("EntryLoader Class_FindMethod loadClass failed, %{public}d", state);
61 break;
62 }
63
64 ani_object isInit;
65 if ((state = static_cast<ani_status>(ArktsAniUtils::CreateAniBoolean(env_, false, isInit))) != ANI_OK) {
66 LOGE("EntryLoader Create Boolean object failed, %{public}d", state);
67 break;
68 }
69
70 if ((state = env_->Object_CallMethod_Ref(
71 (ani_object)linkerRef, loadClassMethod, &entryClassRef, entryStr, isInit)) != ANI_OK) {
72 LOGE("EntryLoader Object_CallMethod_Ref loadClassMethod failed %{public}d %s", state,
73 entryPointName.c_str());
74 ani_error errorInfo;
75 env_->GetUnhandledError(&errorInfo);
76 env_->ResetError();
77 break;
78 }
79 entryClass = static_cast<ani_class>(entryClassRef);
80
81 ani_method entryMethod = nullptr;
82 if (env_->Class_FindMethod(entryClass, "<ctor>", ":V", &entryMethod) != ANI_OK) {
83 LOGE("EntryLoader Class_FindMethod ctor failed");
84 break;
85 }
86
87 ani_object entryObject = nullptr;
88 if (env_->Object_New(entryClass, entryMethod, &entryObject) != ANI_OK) {
89 LOGE("EntryLoader Object_New AbcRuntimeLinker failed");
90 break;
91 }
92 return entryObject;
93 } while (false);
94 return nullptr;
95 }
96
97 namespace NG {
EntryLoader(ani_env * env,const std::string & abcModulePath)98 EntryLoader::EntryLoader(ani_env* env, const std::string& abcModulePath): env_(env)
99 {
100 ani_ref undefined;
101 ANI_CALL(env, GetUndefined(&undefined), return);
102
103 ani_string abcModulePathStr;
104 ANI_CALL(env, String_NewUTF8(abcModulePath.c_str(), abcModulePath.length(), &abcModulePathStr), return);
105
106 ani_type stringCls;
107 ANI_CALL(env, Object_GetType(abcModulePathStr, &stringCls), return);
108
109 ani_array_ref refArray;
110 ANI_CALL(env, Array_New_Ref(stringCls, 1, abcModulePathStr, &refArray), return);
111
112 ani_class cls;
113 ANI_CALL(env, FindClass("Lstd/core/AbcRuntimeLinker;", &cls), return);
114
115 ani_method ctor;
116 ANI_CALL(env, Class_FindMethod(
117 cls, "<ctor>", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V", &ctor), return);
118
119 ANI_CALL(env, Object_New(cls, ctor, &runtimeLinkerObj_, undefined, refArray), return);
120
121 ANI_CALL(env, Class_FindMethod(
122 cls, "loadClass", "Lstd/core/String;Lstd/core/Boolean;:Lstd/core/Class;", &loadClass_), return);
123 }
124
EntryLoader(ani_env * env,const std::vector<uint8_t> & abcContent)125 EntryLoader::EntryLoader(ani_env* env, const std::vector<uint8_t>& abcContent): env_(env)
126 {
127 ani_ref undefined;
128 ANI_CALL(env, GetUndefined(&undefined), return);
129
130 ani_array_byte byteArray;
131 ANI_CALL(env, Array_New_Byte(abcContent.size(), &byteArray), return);
132 ANI_CALL(env, Array_SetRegion_Byte(
133 byteArray, 0, abcContent.size(), reinterpret_cast<const ani_byte*>(abcContent.data())), return);
134
135 ani_type byteArrayCls;
136 ANI_CALL(env, Object_GetType(byteArray, &byteArrayCls), return);
137
138 ani_array_ref refArray;
139 ANI_CALL(env, Array_New_Ref(byteArrayCls, 1, byteArray, &refArray), return);
140
141 ani_class cls;
142 ANI_CALL(env, FindClass("Lstd/core/MemoryRuntimeLinker;", &cls), return);
143
144 ani_method ctor;
145 ANI_CALL(env, Class_FindMethod(
146 cls, "<ctor>", "Lstd/core/RuntimeLinker;[[B:V", &ctor), return);
147
148 ANI_CALL(env, Object_New(cls, ctor, &runtimeLinkerObj_, undefined, refArray), return);
149
150 ANI_CALL(env, Class_FindMethod(
151 cls, "loadClass", "Lstd/core/String;Lstd/core/Boolean;:Lstd/core/Class;", &loadClass_), return);
152 }
153
GetPageEntryObj(const std::string & entryPath) const154 ani_object EntryLoader::GetPageEntryObj(const std::string& entryPath) const
155 {
156 ani_string entryClassStr;
157 ANI_CALL(env_, String_NewUTF8(entryPath.c_str(), entryPath.length(), &entryClassStr), return {});
158
159 ani_ref entryClass;
160 ANI_CALL(env_, Object_CallMethod_Ref(runtimeLinkerObj_, loadClass_, &entryClass, entryClassStr, false), return {});
161
162 ani_method entryCtor;
163 ANI_CALL(env_, Class_FindMethod(static_cast<ani_class>(entryClass), "<ctor>", ":V", &entryCtor), return {});
164
165 ani_object entryObject = nullptr;
166 ANI_CALL(env_, Object_New(static_cast<ani_class>(entryClass), entryCtor, &entryObject), return {});
167
168 return entryObject;
169 }
170 }
171 } // namespace OHOS::Ace