• 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_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