• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef ECMASCRIPT_MODULE_MODULE_PATH_HELPER_H
16 #define ECMASCRIPT_MODULE_MODULE_PATH_HELPER_H
17 
18 #include "ecmascript/base/path_helper.h"
19 
20 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
21 #include "ecmascript/base/string_helper.h"
22 #include "ecmascript/ecma_macros.h"
23 #include "ecmascript/ecma_string.h"
24 #include "ecmascript/ecma_vm.h"
25 #include "ecmascript/global_env.h"
26 #include "ecmascript/js_tagged_value-inl.h"
27 #include "ecmascript/jspandafile/js_pandafile.h"
28 /*
29  * Intra-application cross hap:
30  * baseFileName = 'data/storage/el1/bundle/moduleName/ets/modules.abc';
31  * cross-application:
32  * baseFileName = 'data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc';
33  * recordName = bundleName/moduleName/xxx(entry)/xxx(ets)/xxx(pages)/xxx  specific abc file
34  *
35  * ohmUrl: It's an index information that can uniquely identify module files.
36  * Current ohmUrl has the following five different prefixs:
37  * 1. @bundle:... Identify OpenHarmony modules.
38  *    {project_path}\entry\src\main\ets\pages\Index --> @bundle:bundleName/moduleName/ets/pages/Index
39  *    @namespace: needs to add when import local har or ohosTest import entry file.
40  *    {project_path}\namespace\src\main\ets\pages\Index --> @bundle:bundleName/moduleName@namespace/ets/pages/Index
41  *
42  * 2. @package:... Identify open source third party modules.
43  *    {project_path}\node_modules.ohpm\pkgName\oh_modules\pkgName\xxx\xxx
44  *    --> @package:pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/xxx
45  *
46  * 3. @app:... Identify c++ modules in application.
47  *    libxxx.so --> @app:bundleName/moduleName/xxx
48  *
49  * 4. @native:... Identify system builtin modules.
50  *    system.app --> @native:system.app
51  *
52  * 5. @ohos:... Identify ohos builtin modules.
53  *    @ohos:hilog --> @ohos:hilog
54  */
55 
56 namespace panda::ecmascript {
57 using PathHelper = base::PathHelper;
58 using StringHelper = base::StringHelper;
59 
60 enum ValidateFilePath { ABC, ETS_MODULES };
61 
62 class ModulePathHelper {
63 public:
64     static constexpr std::string_view EXT_NAME_ABC = ".abc";
65     static constexpr std::string_view EXT_NAME_ETS = ".ets";
66     static constexpr std::string_view EXT_NAME_TS = ".ts";
67     static constexpr std::string_view EXT_NAME_JS = ".js";
68     static constexpr std::string_view EXT_NAME_JSON = ".json";
69     static constexpr std::string_view EXT_NAME_Z_SO = ".z.so";
70     static constexpr std::string_view EXT_NAME_D_TS = ".d.ts";
71     static constexpr std::string_view EXT_NAME_MJS = ".mjs";
72     static constexpr std::string_view EXT_NAME_HQF = ".hqf";
73     static constexpr std::string_view PREFIX_NORMALIZED = "@normalized:";
74     static constexpr std::string_view PREFIX_NORMALIZED_SO = "@normalized:Y";
75     static constexpr std::string_view PREFIX_NORMALIZED_NOT_SO = "@normalized:N";
76     static constexpr std::string_view PREFIX_NORMALIZED_NOT_CROSS_HAP_FILE = "@normalized:N&&&";
77     static constexpr std::string_view PREFIX_BUNDLE = "@bundle:";
78     static constexpr std::string_view PREFIX_MODULE = "@module:";
79     static constexpr std::string_view PREFIX_PACKAGE = "@package:";
80     static constexpr std::string_view PREFIX_ETS = "ets/";
81     static constexpr std::string_view PREFIX_LIB = "lib";
82     static constexpr std::string_view REQUIRE_NAITVE_MODULE_PREFIX = "@native:";
83     static constexpr std::string_view REQUIRE_NAPI_OHOS_PREFIX = "@ohos:";
84     static constexpr std::string_view REQUIRE_NAPI_APP_PREFIX = "@app:";
85     static constexpr std::string_view RAW_ARKUIX_PREFIX = "@arkui-x.";
86     static constexpr std::string_view NPM_PATH_SEGMENT = "node_modules";
87     static constexpr std::string_view PACKAGE_PATH_SEGMENT = "pkg_modules";
88     static constexpr std::string_view PACKAGE_ENTRY_FILE = "/index";
89     static constexpr std::string_view BUNDLE_INSTALL_PATH = "/data/storage/el1/bundle/";
90     static constexpr std::string_view MERGE_ABC_ETS_MODULES = "/ets/modules.abc";
91     static constexpr std::string_view ABC = ".abc";
92     static constexpr std::string_view MODULE_DEFAULE_ETS = "/ets/";
93     static constexpr std::string_view BUNDLE_SUB_INSTALL_PATH = "/data/storage/el1/";
94     static constexpr std::string_view PREVIEW_OF_ACROSS_HAP_FLAG = "[preview]";
95     static constexpr std::string_view PREVIER_TEST_DIR = ".test";
96     static constexpr std::string_view PHYCICAL_FILE_PATH = "/src/main";
97     static constexpr std::string_view VMA_NAME_ARKTS_CODE = "ArkTS Code";
98     static constexpr std::string_view ENTRY_MAIN_FUNCTION = "_GLOBAL::func_main_0";
99     static constexpr std::string_view ENTRY_FUNCTION_NAME = "func_main_0";
100     static constexpr std::string_view TRUE_FLAG = "true";
101 
102     static constexpr size_t MAX_PACKAGE_LEVEL = 1;
103     static constexpr size_t SEGMENTS_LIMIT_TWO = 2;
104     static constexpr size_t EXT_NAME_ABC_LEN = 4;
105     static constexpr size_t EXT_NAME_ETS_LEN = 4;
106     static constexpr size_t EXT_NAME_TS_LEN = 3;
107     static constexpr size_t EXT_NAME_JS_LEN = 3;
108     static constexpr size_t EXT_NAME_JSON_LEN = 5;
109     static constexpr size_t PREFIX_BUNDLE_LEN = 8;
110     static constexpr size_t PREFIX_MODULE_LEN = 8;
111     static constexpr size_t PREFIX_PACKAGE_LEN = 9;
112     static constexpr size_t PREFIX_NORMALIZED_LEN = 15;
113     static constexpr size_t PACKAGE_PATH_SEGMENT_LEN = 11;
114     static constexpr size_t NATIVE_PREFIX_SIZE = 8;
115     static constexpr size_t OHOS_PREFIX_SIZE = 6;
116     static constexpr size_t APP_PREFIX_SIZE = 5;
117     static constexpr size_t BUNDLE_INSTALL_PATH_LEN = 25;
118     static constexpr size_t PHYCICAL_FILE_PATH_LEN = 10;
119     static constexpr size_t NORMALIZED_OHMURL_ARGS_NUM = 5;
120     static constexpr size_t NORMALIZED_MODULE_NAME_INDEX = 1;
121     static constexpr size_t NORMALIZED_BUNDLE_NAME_INDEX = 2;
122     static constexpr size_t NORMALIZED_IMPORT_PATH_INDEX = 3;
123     static constexpr size_t NORMALIZED_VERSION_INDEX = 4;
124     static constexpr size_t CURRENT_DIREATORY_TAG_LEN = 2;
125     static constexpr size_t SO_PREFIX_LEN = 3;
126     static constexpr size_t SO_SUFFIX_LEN = 3;
127 
128     static constexpr size_t PKGINFO_PACKAGE_NAME_INDEX = 1;
129     static constexpr size_t PKGINFO_BUDNLE_NAME_INDEX = 3;
130     static constexpr size_t PKGINFO_MODULE_NAME_INDEX = 5;
131     static constexpr size_t PKGINFO_VERSION_INDEX = 7;
132     static constexpr size_t PKGINFO_ENTRY_PATH_INDEX = 9;
133     static constexpr size_t PKGINFO_IS_SO_INDEX = 11;
134 
135     static CString PUBLIC_API ConcatFileNameWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile,
136         CString &baseFileName, const CString &recordName, const CString &requestName);
137     static void ParseAbcPathAndOhmUrl(EcmaVM *vm, const CString &inputFileName, CString &outBaseFileName,
138                                       CString &outEntryPoint);
139     static CString ConcatUnifiedOhmUrl(const CString &bundleName, const CString &pkgname, const CString &entryPath,
140                                        const CString &path, const CString &version);
141     static CString ConcatUnifiedOhmUrl(const CString &bundleName, const CString &normalizedpath,
142         const CString &version);
143     static CString ConcatPreviewTestUnifiedOhmUrl(const CString &bundleName, const CString &pkgname,
144         const CString &path, const CString &version);
145     static CString ConcatHspFileNameCrossBundle(const CString &bundleName, const CString &moduleName);
146     static CString ConcatHspFileName(const CString &moduleName);
147     static CString ThrowInvalidOhmurlError(EcmaVM *vm, const CString &oldEntryPoint);
148     static CString TransformToNormalizedOhmUrl(EcmaVM *vm, const CString &inputFileName, const CString &baseFileName,
149         const CString &oldEntryPoint);
150     static CString ParseUrl(EcmaVM *vm, const CString &recordName);
151     static CString ParsePrefixBundle(JSThread *thread, const JSPandaFile *jsPandaFile,
152         [[maybe_unused]] CString &baseFileName, CString moduleRequestName, [[maybe_unused]] CString recordName);
153     static CString ParseNormalizedOhmUrl(JSThread *thread, CString &baseFileName, const CString &recordName,
154                                          CString requestName);
155     static CString MakeNewRecord(JSThread *thread, const JSPandaFile *jsPandaFile, CString &baseFileName,
156                                  const CString &recordName, const CString &requestName);
157     static CString FindOhpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &ohpmPath,
158                                       const CString &requestName);
159     static CString FindPackageInTopLevelWithNamespace(const JSPandaFile *jsPandaFile, const CString &requestName,
160                                                       const CString &recordName);
161     static CString ParseOhpmPackage(const JSPandaFile *jsPandaFile, const CString &recordName,
162                                     const CString &requestName);
163     static CString ParseThirdPartyPackage(const JSPandaFile *jsPandaFile, const CString &recordName,
164                                           const CString &requestName, const CString &packagePath);
165     static CString ParseThirdPartyPackage(const JSPandaFile *jsPandaFile, const CString &recordName,
166                                           const CString &requestName);
167     static void ResolveCurrentPath(CString &dirPath, CString &fileName, const JSPandaFile *jsPandaFile);
168     static CString FindNpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint);
169     static CString FindPackageInTopLevel(const JSPandaFile *jsPandaFile, const CString &requestName,
170                                          const CString &packagePath);
171     static bool IsImportFile(const CString &moduleRequestName);
172     static CString RemoveSuffix(const CString &requestName);
173     static bool NeedTranstale(const CString &requestName);
174     static bool NeedTranslateToNormalized(const CString &requestName);
175     static void TranstaleExpressionInput(const JSPandaFile *jsPandaFile, CString &requestPath);
176     static CString GetModuleNameWithBaseFile(const CString &baseFileName);
177     static CString TranslateExpressionInputWithEts(JSThread *thread, const JSPandaFile *jsPandaFile,
178                                                    const CString &baseFileName, const CString &requestName);
179     static void ParseCrossModuleFile(const JSPandaFile *jsPandaFile, CString &requestPath);
180     static CString ReformatPath(const CString& requestName);
181     static CString TranslateExpressionToNormalized(JSThread *thread, const JSPandaFile *jsPandaFile,
182                                                    [[maybe_unused]] CString &baseFileName, const CString &recordName,
183                                                    CString &requestPath);
184     static CVector<CString> GetPkgContextInfoListElements(EcmaVM *vm, const CString &moduleName,
185                                                           const CString &packageName);
186     static CString TranslateNapiFileRequestPath(JSThread *thread, const CString &modulePath,
187                                                 const CString &requestName);
188     static CVector<CString> SplitNormalizedOhmurl(const CString &ohmurl);
189     static CString ConcatImportFileNormalizedOhmurl(const CString &recordPath, const CString &requestName,
190                                                     const CString &version = "");
191     static CString ConcatNativeSoNormalizedOhmurl(const CString &moduleName, const CString &bundleName,
192                                                   const CString &pkgName, const CString &version);
193     static CString ConcatNotSoNormalizedOhmurl(const CString &moduleName, const CString &bundleName,
194                                                const CString &pkgName, const CString &entryPath,
195                                                const CString &version);
196     static CString ConcatMergeFileNameToNormalized(JSThread *thread, const JSPandaFile *jsPandaFile,
197                                                    CString &baseFileName, const CString &recordName,
198                                                    CString requestName);
199     static CVector<CString> SplitNormalizedRecordName(const CString &recordName);
200     static CString ConcatImportFileNormalizedOhmurlWithRecordName(JSThread *thread, const JSPandaFile *jsPandaFile,
201                                                                   CString &baseFileName, const CString &recordName,
202                                                                   const CString &requestName);
203     static void ConcatOtherNormalizedOhmurl(EcmaVM *vm, const JSPandaFile *jsPandaFile,
204                                             [[maybe_unused]] const CString &baseFileName, CString &requestPath);
205     static CString ConcatNormalizedOhmurlWithData(const CVector<CString> &data, const CString &pkgName,
206                                                   CString &entryPath);
207     static CString GetBundleNameWithRecordName(EcmaVM *vm, const CString &recordName);
208     static CString Utf8ConvertToString(JSThread *thread, JSTaggedValue str);
209 
210     static CString ParseFileNameToVMAName(const CString &filename);
211     static CString ConcatOtherNormalizedOhmurlWithFilePath(EcmaVM *vm, size_t filePathPos, const CString &moduleName,
212                                                            const CString &requestPath);
213     static bool IsOhmUrl(const CString &str);
214     static bool CheckAndGetRecordName(JSThread *thread, const CString &ohmUrl, CString &recordName);
215     static bool ValidateAbcPath(const CString &baseFileName, ValidateFilePath checkMode);
216     static std::pair<std::string, std::string> ResolveOhmUrl(std::string ohmUrl);
217     static std::pair<std::string, std::string> ResolveOhmUrlStartWithBundle(const std::string &ohmUrl);
218     static std::pair<std::string, std::string> ResolveOhmUrlStartWithNormalized(const std::string &ohmUrl);
219 
ResolvePath(const char * path)220     inline static std::pair<CString, CString> ResolvePath(const char *path)
221     {
222         CString filePath(path);
223         size_t index = filePath.find_last_of('/');
224         if (index == std::string::npos) {
225             LOG_FULL(FATAL) << "The OhmUrl is invalid";
226         }
227         CString entry = filePath.substr(index + 1);
228         return {filePath + ABC.data(), entry};
229     }
230 
231     /*
232      * Before: /data/storage/el1/bundle/moduleName/ets/modules.abc
233      * After:  bundle/moduleName
234      */
ParseHapPath(const CString & baseFileName)235     inline static std::string ParseHapPath(const CString &baseFileName)
236     {
237         CString bundleSubInstallName(BUNDLE_SUB_INSTALL_PATH);
238         size_t startStrLen = bundleSubInstallName.length();
239         if (baseFileName.length() > startStrLen && baseFileName.compare(0, startStrLen, bundleSubInstallName) == 0) {
240             CString hapPath = baseFileName.substr(startStrLen);
241             size_t pos = hapPath.find(MERGE_ABC_ETS_MODULES);
242             if (pos != CString::npos) {
243                 return hapPath.substr(0, pos).c_str();
244             }
245         }
246         return {};
247     }
248 
249     /*
250      * Before: xxx
251      * After:  xxx || xxx/index
252      */
ConfirmLoadingIndexOrNot(const JSPandaFile * jsPandaFile,const CString & packageEntryPoint)253     inline static CString ConfirmLoadingIndexOrNot(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint)
254     {
255         CString entryPoint = packageEntryPoint;
256         if (jsPandaFile->HasRecord(entryPoint)) {
257             return entryPoint;
258         }
259         // Possible import directory
260         entryPoint += PACKAGE_ENTRY_FILE;
261         entryPoint = PathHelper::NormalizePath(entryPoint);
262         if (jsPandaFile->HasRecord(entryPoint)) {
263             return entryPoint;
264         }
265         return {};
266     }
267 
IsNativeModuleRequest(const CString & requestName)268     inline static bool IsNativeModuleRequest(const CString &requestName)
269     {
270         if (requestName[0] != PathHelper::NAME_SPACE_TAG) {
271             return false;
272         }
273         if (StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAPI_OHOS_PREFIX) ||
274             StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAPI_APP_PREFIX) ||
275             StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAITVE_MODULE_PREFIX)) {
276             return true;
277         }
278         return false;
279     }
280 
281     /*
282      * Before: bundleName/moduleName/ets/xxx/xxx
283      * After:  moduleName
284      */
GetModuleName(const CString & recordName)285     inline static CString GetModuleName(const CString& recordName)
286     {
287         if (size_t pos1 = recordName.find(PathHelper::SLASH_TAG); pos1 != CString::npos) {
288             pos1++;
289             if (const size_t pos2 = recordName.find(PathHelper::SLASH_TAG, pos1); pos2 != CString::npos) {
290                 CString moduleName = recordName.substr(pos1, pos2 - pos1);
291                 PathHelper::DeleteNamespace(moduleName);
292                 return moduleName;
293             }
294         }
295         return {};
296     }
297 
298     /*
299      * Before: &moduleName/src/xxx
300      * After:  moduleName
301      */
GetModuleNameWithNormalizedName(const CString & recordName)302     inline static CString GetModuleNameWithNormalizedName(const CString& recordName)
303     {
304         size_t pos1 = recordName.find(PathHelper::NORMALIZED_OHMURL_TAG);
305         if (pos1 != CString::npos) {
306             pos1++;
307             size_t pos2 = recordName.find(PathHelper::SLASH_TAG, pos1);
308             if (pos2 != CString::npos) {
309                 CString moduleName = recordName.substr(pos1, pos2 - pos1);
310                 return moduleName;
311             }
312         }
313         return {};
314     }
315 
316     /*
317      * Before: bundleName/moduleName
318      * After:  moduleName
319      */
GetModuleNameWithPath(const CString & modulePath)320     inline static CString GetModuleNameWithPath(const CString& modulePath)
321     {
322         size_t pos1 = modulePath.find(PathHelper::SLASH_TAG);
323         if (pos1 != CString::npos) {
324             pos1++;
325             return modulePath.substr(pos1, modulePath.size() - pos1 + 1);
326         }
327         return {};
328     }
329     /*
330      * Before: @xxx.
331      * After:  @xxx:
332      */
ChangeTag(CString & path)333     inline static bool ChangeTag(CString &path)
334     {
335         if (path[0] == PathHelper::NAME_SPACE_TAG) {
336             size_t pos = path.find(PathHelper::POINT_TAG);
337             if (pos != CString::npos) {
338                 path.replace(pos, 1, PathHelper::COLON_TAG); // 1: length
339                 return true;
340             }
341         }
342         return false;
343     }
344 
345     /*
346      * Before: moduleName
347      * After:  data/storage/el1/bundle/moduleName/ets/modules.abc
348      */
ConcatPandaFilePath(const CString & moduleName)349     inline static CString ConcatPandaFilePath(const CString &moduleName)
350     {
351         if (moduleName.empty()) {
352             return {};
353         }
354         return base::ConcatToCString(BUNDLE_INSTALL_PATH, moduleName, MERGE_ABC_ETS_MODULES);
355     }
356 
GetBundleNameFromNormalized(const EcmaVM * vm,const CString & moduleName)357     inline static CString GetBundleNameFromNormalized(const EcmaVM *vm, const CString &moduleName)
358     {
359         CVector<CString> res = SplitNormalizedOhmurl(moduleName);
360         if (res.size() != NORMALIZED_OHMURL_ARGS_NUM) {
361             LOG_FULL(ERROR) << "GetBundleNameFromNormalized Invalid normalized ohmurl";
362             return "";
363         }
364         CString bundleName = res[NORMALIZED_BUNDLE_NAME_INDEX];
365         if (bundleName.empty()) {
366             return vm->GetBundleName();
367         }
368         return bundleName;
369     }
370 
GetNormalizedPathFromOhmUrl(const CString & moduleName)371     inline static CString GetNormalizedPathFromOhmUrl(const CString &moduleName)
372     {
373         CVector<CString> res = SplitNormalizedOhmurl(moduleName);
374         if (res.size() != NORMALIZED_OHMURL_ARGS_NUM) {
375             LOG_FULL(ERROR) << "GetNormalizedPathFromOhmUrl Invalid normalized ohmurl";
376             return "";
377         }
378         CString soName = res[NORMALIZED_IMPORT_PATH_INDEX];
379         // Delete the prefix "lib" and suffix ".so".
380         soName = soName.substr(SO_PREFIX_LEN, soName.size() - SO_PREFIX_LEN - SO_SUFFIX_LEN);
381         return soName;
382     }
383 };
384 } // namespace panda::ecmascript
385 #endif // ECMASCRIPT_MODULE_MODULE_PATH_HELPER_H