• 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 #include "ecmascript/module/module_path_helper.h"
16 
17 namespace panda::ecmascript {
18 /*
19  * This function use recordName, requestName to get baseFileName and entryPoint.
20  */
ConcatFileNameWithMerge(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,CString recordName,CString requestName)21 CString ModulePathHelper::ConcatFileNameWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile,
22     CString &baseFileName, CString recordName, CString requestName)
23 {
24     if (thread->GetEcmaVM()->IsNormalizedOhmUrlPack() && !StringHelper::StringStartWith(requestName, PREFIX_BUNDLE) &&
25         !StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) {
26         return ConcatMergeFileNameToNormalized(thread, jsPandaFile, baseFileName, recordName, requestName);
27     }
28 
29     if (StringHelper::StringStartWith(requestName, PREFIX_BUNDLE)) {
30         return ParsePrefixBundle(thread, jsPandaFile, baseFileName, requestName, recordName);
31     } else if (StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) {
32         return requestName.substr(PREFIX_PACKAGE_LEN);
33     } else if (IsImportFile(requestName)) {
34         // this branch save for require/dynamic import/old version sdk
35         // load a relative pathName.
36         // requestName: ./ || ./xxx/xxx.js || ../xxx/xxx.js || ./xxx/xxx
37         return MakeNewRecord(thread, jsPandaFile, baseFileName, recordName, requestName);
38     } else if (StringHelper::StringStartWith(requestName, PREFIX_ETS)) {
39         CString entryPoint = TranslateExpressionInputWithEts(thread, jsPandaFile, baseFileName, requestName);
40         if (entryPoint.empty()) {
41             THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, entryPoint);
42         }
43         return entryPoint;
44     } else {
45         // this branch save for require/dynamic import/old version sdk
46         // requestName: requestPkgName
47         CString entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName);
48         if (entryPoint.empty()) {
49             THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, entryPoint);
50         }
51         return entryPoint;
52     }
53     LOG_FULL(FATAL) << "this branch is unreachable";
54     UNREACHABLE();
55 }
56 
ConcatMergeFileNameToNormalized(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & recordName,CString requestName)57 CString ModulePathHelper::ConcatMergeFileNameToNormalized(JSThread *thread, const JSPandaFile *jsPandaFile,
58     CString &baseFileName, const CString &recordName, CString requestName)
59 {
60     CString prefix(1, PathHelper::NORMALIZED_OHMURL_TAG);
61     if (StringHelper::StringStartWith(requestName, prefix)) {
62         return requestName;
63     } else if (IsImportFile(requestName)) {
64         // this branch save for import "xxx.js" in npm
65         CString inputPath = requestName;
66         CString entryPoint = ConcatImportFileNormalizedOhmurlWithRecordName(thread, jsPandaFile, baseFileName,
67             recordName, requestName);
68         if (entryPoint.empty()) {
69             THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, inputPath, recordName, requestName);
70         }
71         return entryPoint;
72     } else {
73         // this branch save for require npm
74         TranslateExpressionToNormalized(thread, jsPandaFile, baseFileName, recordName, requestName);
75     }
76     return ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName);
77 }
78 
79 /*
80  * Before: requestName: ../xxx1/xxx2 || ./xxx1
81  * After:  &entryPath&version
82  */
ConcatImportFileNormalizedOhmurlWithRecordName(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & recordName,const CString & requestName)83 CString ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(JSThread *thread,
84     const JSPandaFile *jsPandaFile, CString &baseFileName, const CString &recordName, const CString &requestName)
85 {
86     CString entryPoint;
87     CVector<CString> res = SplitNormalizedRecordName(recordName);
88     CString path = PathHelper::NORMALIZED_OHMURL_TAG + res[NORMALIZED_IMPORT_PATH_INDEX];
89     CString version = res[NORMALIZED_VERSION_INDEX];
90     CString moduleRequestName = requestName;
91     moduleRequestName = RemoveSuffix(moduleRequestName);
92     size_t pos = moduleRequestName.find(PathHelper::CURRENT_DIREATORY_TAG);
93     if (pos == 0) {
94         moduleRequestName = moduleRequestName.substr(CURRENT_DIREATORY_TAG_LEN);
95     }
96     pos = path.rfind(PathHelper::SLASH_TAG);
97     if (pos != CString::npos) {
98         entryPoint = path.substr(0, pos + 1) + moduleRequestName;
99     } else {
100         entryPoint = moduleRequestName;
101     }
102     entryPoint = PathHelper::NormalizePath(entryPoint);
103     moduleRequestName = ConcatImportFileNormalizedOhmurl(entryPoint, "", version);
104     if (jsPandaFile->HasRecord(moduleRequestName)) {
105         return moduleRequestName;
106     }
107     // requestName may be a folder
108     entryPoint += PACKAGE_ENTRY_FILE;
109     entryPoint = PathHelper::NormalizePath(entryPoint);
110     moduleRequestName = ConcatImportFileNormalizedOhmurl(entryPoint, "", version);
111     if (jsPandaFile->HasRecord(moduleRequestName)) {
112         return moduleRequestName;
113     }
114 
115     // requestName may be a packageName
116     moduleRequestName = requestName;
117     ConcatOtherNormalizedOhmurl(thread->GetEcmaVM(), jsPandaFile, baseFileName, moduleRequestName);
118     moduleRequestName = ParseNormalizedOhmUrl(thread, baseFileName, recordName, moduleRequestName);
119     if (jsPandaFile->HasRecord(moduleRequestName)) {
120         return moduleRequestName;
121     }
122     return CString();
123 }
124 
ReformatPath(CString requestName)125 CString ModulePathHelper::ReformatPath(CString requestName)
126 {
127     CString normalizeStr;
128     if (StringHelper::StringStartWith(requestName, PACKAGE_PATH_SEGMENT) ||
129         StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) {
130         auto pos = requestName.rfind(PACKAGE_PATH_SEGMENT);
131         ASSERT(pos != CString::npos);
132         normalizeStr = requestName.substr(pos + 1);
133     } else if (StringHelper::StringStartWith(requestName, REQUIRE_NAPI_APP_PREFIX)) {
134         auto pos = requestName.find(PathHelper::SLASH_TAG);
135         pos = requestName.find(PathHelper::SLASH_TAG, pos + 1);
136         ASSERT(pos != CString::npos);
137         normalizeStr = requestName.substr(pos + 1);
138     } else {
139         normalizeStr = requestName;
140     }
141     return normalizeStr;
142 }
143 
144 /*
145  * Before: inputFileName: 1. /data/storage/el1/bundle/moduleName@namespace/ets/xxx/xxx.abc
146                           2. @bundle:bundleName/moduleName/ets/xxx/xxx.abc
147                           3. moduleName/ets/xxx/xxx.abc
148                           4. .test/xxx/xxx.abc
149                           5. xxx/xxx.abc
150  * After:  outBaseFileName: /data/storage/el1/bundle/moduleName/ets/modules.abc
151  *         outEntryPoint: bundleName/moduleName/ets/xxx/xxx
152  */
ParseAbcPathAndOhmUrl(EcmaVM * vm,const CString & inputFileName,CString & outBaseFileName,CString & outEntryPoint)153 void ModulePathHelper::ParseAbcPathAndOhmUrl(EcmaVM *vm, const CString &inputFileName,
154     CString &outBaseFileName, CString &outEntryPoint)
155 {
156     size_t pos = CString::npos;
157     if (inputFileName.length() > BUNDLE_INSTALL_PATH_LEN &&
158         inputFileName.compare(0, BUNDLE_INSTALL_PATH_LEN, BUNDLE_INSTALL_PATH) == 0) {
159         pos = BUNDLE_INSTALL_PATH_LEN;
160     }
161     if (pos != CString::npos) {
162         // inputFileName: /data/storage/el1/bundle/moduleName@namespace/ets/xxx/xxx.abc
163         pos = inputFileName.find(PathHelper::SLASH_TAG, BUNDLE_INSTALL_PATH_LEN);
164         if (pos == CString::npos) { // LCOV_EXCL_BR_LINE
165             LOG_FULL(FATAL) << "Invalid Ohm url, please check.";
166         }
167         CString moduleName = inputFileName.substr(BUNDLE_INSTALL_PATH_LEN, pos - BUNDLE_INSTALL_PATH_LEN);
168         PathHelper::DeleteNamespace(moduleName);
169         outBaseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
170         outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + inputFileName.substr(BUNDLE_INSTALL_PATH_LEN);
171     } else {
172         // Temporarily handle the relative path sent by arkui
173         // inputFileName: @bundle:bundleName/moduleName/ets/xxx/xxx.abc
174         if (StringHelper::StringStartWith(inputFileName, PREFIX_BUNDLE)) {
175             outEntryPoint = inputFileName.substr(PREFIX_BUNDLE_LEN);
176             outBaseFileName = ParseUrl(vm, outEntryPoint);
177         } else {
178 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
179             // inputFileName: moduleName/ets/xxx/xxx.abc
180             outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + inputFileName;
181 #else
182             // if the inputFileName starts with '.test', the preview test page is started.
183             // in this case, the path ets does not need to be combined.
184             // inputFileName: .test/xxx/xxx.abc
185             if (StringHelper::StringStartWith(inputFileName, PREVIER_TEST_DIR)) {
186                 outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + vm->GetModuleName() +
187                                 PathHelper::SLASH_TAG + inputFileName;
188             } else {
189                 // inputFileName: xxx/xxx.abc
190                 outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + vm->GetModuleName() +
191                                 MODULE_DEFAULE_ETS + inputFileName;
192             }
193 #endif
194         }
195     }
196     if (StringHelper::StringEndWith(outEntryPoint, EXT_NAME_ABC)) {
197         outEntryPoint.erase(outEntryPoint.length() - EXT_NAME_ABC_LEN, EXT_NAME_ABC_LEN);
198     }
199     if (vm->IsNormalizedOhmUrlPack()) {
200         outEntryPoint = TransformToNormalizedOhmUrl(vm, inputFileName, outBaseFileName, outEntryPoint);
201     }
202 }
203 
204 // Unified ohmUrl used be cached: [<bundle name>?]&<pkg name + /src/main + path>&[<version>?]
ConcatUnifiedOhmUrl(const CString & bundleName,const CString & pkgname,const CString & entryPath,const CString & path,const CString & version)205 CString ModulePathHelper::ConcatUnifiedOhmUrl(const CString &bundleName, const CString &pkgname,
206     const CString &entryPath, const CString &path, const CString &version)
207 {
208     if (entryPath.size() != 0) {
209         // entryPath is src/xxx/
210         return bundleName + PathHelper::NORMALIZED_OHMURL_TAG + pkgname + PathHelper::SLASH_TAG + entryPath + path +
211             PathHelper::NORMALIZED_OHMURL_TAG + version;
212     }
213     return bundleName + PathHelper::NORMALIZED_OHMURL_TAG + pkgname + PHYCICAL_FILE_PATH + path +
214         PathHelper::NORMALIZED_OHMURL_TAG + version;
215 }
216 
ConcatUnifiedOhmUrl(const CString & bundleName,const CString & normalizedpath,const CString & version)217 CString ModulePathHelper::ConcatUnifiedOhmUrl(const CString &bundleName, const CString &normalizedpath,
218     const CString &version)
219 {
220     return bundleName + PathHelper::NORMALIZED_OHMURL_TAG + normalizedpath + PathHelper::NORMALIZED_OHMURL_TAG +
221         version;
222 }
223 
ConcatPreviewTestUnifiedOhmUrl(const CString & bundleName,const CString & pkgname,const CString & path,const CString & version)224 CString ModulePathHelper::ConcatPreviewTestUnifiedOhmUrl(const CString &bundleName, const CString &pkgname,
225     const CString &path, const CString &version)
226 {
227     return bundleName + PathHelper::NORMALIZED_OHMURL_TAG + pkgname + path + PathHelper::NORMALIZED_OHMURL_TAG +
228         version;
229 }
230 
ConcatHspFileNameCrossBundle(const CString & bundleName,const CString & moduleName)231 CString ModulePathHelper::ConcatHspFileNameCrossBundle(const CString &bundleName, const CString &moduleName)
232 {
233     CString bundlePath = BUNDLE_INSTALL_PATH;
234     return bundlePath + bundleName + PathHelper::SLASH_TAG + moduleName + PathHelper::SLASH_TAG + moduleName +
235         MERGE_ABC_ETS_MODULES;
236 }
237 
ConcatHspFileName(const CString & moduleName)238 CString ModulePathHelper::ConcatHspFileName(const CString &moduleName)
239 {
240     CString bundlePath = BUNDLE_INSTALL_PATH;
241     return bundlePath + moduleName + MERGE_ABC_ETS_MODULES;
242 }
243 
TransformToNormalizedOhmUrl(EcmaVM * vm,const CString & inputFileName,const CString & baseFileName,const CString & oldEntryPoint)244 CString ModulePathHelper::TransformToNormalizedOhmUrl(EcmaVM *vm, const CString &inputFileName,
245     const CString &baseFileName, const CString &oldEntryPoint)
246 {
247     CString prefix(1, PathHelper::NORMALIZED_OHMURL_TAG);
248     if (oldEntryPoint == ENTRY_MAIN_FUNCTION || StringHelper::StringStartWith(oldEntryPoint, prefix)) {
249         return oldEntryPoint;
250     }
251     size_t pos = oldEntryPoint.find(PathHelper::SLASH_TAG);
252     size_t pathPos = oldEntryPoint.find(PathHelper::SLASH_TAG, pos + 1);
253     LOG_ECMA(DEBUG) << "TransformToNormalizedOhmUrl inputFileName: " << inputFileName << " oldEntryPoint: " <<
254         oldEntryPoint;
255     if (pos == CString::npos || pathPos == CString::npos) {
256         CString errorMsg = "TransformToNormalizedOhmUrl Invalid Ohmurl: " + oldEntryPoint + ", please check.";
257         THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(vm->GetJSThread(), ErrorType::SYNTAX_ERROR, errorMsg.c_str(),
258             oldEntryPoint);
259     }
260     CString path = oldEntryPoint.substr(pathPos);
261     CString moduleName = oldEntryPoint.substr(pos + 1, pathPos - pos - 1);
262     if (moduleName.find(PathHelper::NAME_SPACE_TAG) != CString::npos) {
263         moduleName = PathHelper::GetHarName(moduleName);
264     }
265     CString pkgname = vm->GetPkgName(moduleName);
266     CString currentModuleName = GetModuleNameWithBaseFile(baseFileName);
267     if (currentModuleName.size() == 0) {
268         currentModuleName = moduleName;
269     }
270     CVector<CString> data = GetPkgContextInfoListElements(vm, currentModuleName, pkgname);
271     CString version;
272     CString entryPath;
273     if (data.size() > 0) {
274         version = data[PKGINFO_VERSION_INDEX];
275         entryPath = data[PKGINFO_ENTRY_PATH_INDEX];
276     } else {
277         return oldEntryPoint;
278     }
279     // If the subPath starts with '.test', it is a preview test, no need to splice the entry path.
280     CString subPath = oldEntryPoint.substr(pathPos + 1);
281     if (StringHelper::StringStartWith(subPath, PREVIER_TEST_DIR)) {
282         return ConcatPreviewTestUnifiedOhmUrl("", pkgname, path, version);
283     }
284     // When the entry path ends with a slash (/), use the entry path to concatenate ohmurl.
285     CString endStr(1, PathHelper::SLASH_TAG);
286     if (entryPath.size() != 0 && StringHelper::StringEndWith(entryPath, endStr)) {
287         size_t endPos = entryPath.rfind(PathHelper::SLASH_TAG);
288         entryPath = entryPath.substr(0, endPos);
289         return ConcatUnifiedOhmUrl("", pkgname, entryPath, path, version);
290     }
291     // bundleName and entryPath is empty.
292     return ConcatUnifiedOhmUrl("", pkgname, "", path, version);
293 }
294 
295 /*
296  * Before: recordName: bundleName/moduleName@namespace/xxx/xxx.abc
297  * After: Intra-application cross hap:   /data/storage/el1/bundle/bundleName/ets/modules.abc
298  *        Cross-application:             /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
299  */
ParseUrl(EcmaVM * vm,const CString & recordName)300 CString ModulePathHelper::ParseUrl(EcmaVM *vm, const CString &recordName)
301 {
302     CVector<CString> vec;
303     StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO);
304     if (vec.size() < SEGMENTS_LIMIT_TWO) {
305         LOG_ECMA(DEBUG) << "ParseUrl SplitString filed, please check Url" << recordName;
306         return CString();
307     }
308     CString bundleName = vec[0];
309     CString moduleName = vec[1];
310     PathHelper::DeleteNamespace(moduleName);
311 
312     CString baseFileName;
313     if (bundleName != vm->GetBundleName()) {
314         // Cross-application
315         baseFileName = BUNDLE_INSTALL_PATH + bundleName + PathHelper::SLASH_TAG + moduleName +
316                        PathHelper::SLASH_TAG + moduleName + MERGE_ABC_ETS_MODULES;
317     } else {
318         // Intra-application cross hap
319         baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
320     }
321     return baseFileName;
322 }
323 
324 /*
325  * Before: moduleRequestName: @bundle:bundleName/moduleName@namespace/ets/xxx
326  * After:  baseFileName: 1./data/storage/el1/bundle/moduleName/ets/modules.abc
327  *                       2./data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
328  *         entryPoint:   bundleName/moduleName@namespace/ets/xxx
329  */
ParsePrefixBundle(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,CString moduleRequestName,CString recordName)330 CString ModulePathHelper::ParsePrefixBundle(JSThread *thread, const JSPandaFile *jsPandaFile,
331     [[maybe_unused]] CString &baseFileName, CString moduleRequestName, [[maybe_unused]] CString recordName)
332 {
333     EcmaVM *vm = thread->GetEcmaVM();
334     moduleRequestName = moduleRequestName.substr(PREFIX_BUNDLE_LEN);
335     CString entryPoint = moduleRequestName;
336     if (jsPandaFile->IsRecordWithBundleName()) {
337         CVector<CString> vec;
338         StringHelper::SplitString(moduleRequestName, vec, 0, SEGMENTS_LIMIT_TWO);
339         if (vec.size() < SEGMENTS_LIMIT_TWO) { // LCOV_EXCL_BR_LINE
340             LOG_ECMA(FATAL) << " Exceptional module path : " << moduleRequestName << ", abc path: " <<
341                 baseFileName << ", current file name: " << recordName;
342         }
343         CString bundleName = vec[0];
344         CString moduleName = vec[1];
345         PathHelper::DeleteNamespace(moduleName);
346 
347 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
348         if (bundleName != vm->GetBundleName()) {
349             baseFileName = BUNDLE_INSTALL_PATH + bundleName + PathHelper::SLASH_TAG + moduleName +
350                            PathHelper::SLASH_TAG + moduleName + MERGE_ABC_ETS_MODULES;
351         } else if (moduleName != vm->GetModuleName()) {
352             baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
353         } else {
354             // Support multi-module card service
355             baseFileName = vm->GetAssetPath();
356         }
357 #else
358         CVector<CString> currentVec;
359         StringHelper::SplitString(moduleRequestName, currentVec, 0, SEGMENTS_LIMIT_TWO);
360         if (currentVec.size() < SEGMENTS_LIMIT_TWO) { // LCOV_EXCL_BR_LINE
361             LOG_ECMA(FATAL) << " Exceptional module path : " << moduleRequestName << ", abc path: " <<
362                 baseFileName << ", current file name: " << recordName;
363         }
364         CString currentModuleName = currentVec[1];
365         PathHelper::DeleteNamespace(currentModuleName);
366         if (bundleName != vm->GetBundleName()) {
367             baseFileName = BUNDLE_INSTALL_PATH + bundleName + PathHelper::SLASH_TAG + moduleName +
368                            PathHelper::SLASH_TAG + moduleName + MERGE_ABC_ETS_MODULES;
369         } else if (currentModuleName != vm->GetModuleName()) {
370             baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
371         }
372 #endif
373     } else {
374         PathHelper::AdaptOldIsaRecord(entryPoint);
375     }
376     return entryPoint;
377 }
378 
379 
ParseNormalizedOhmUrl(JSThread * thread,CString & baseFileName,const CString & recordName,CString requestName)380 CString ModulePathHelper::ParseNormalizedOhmUrl(JSThread *thread, CString &baseFileName, const CString &recordName,
381     CString requestName)
382 {
383     ASSERT(StringHelper::StringStartWith(requestName, PREFIX_NORMALIZED_NOT_SO));
384     CVector<CString> res = SplitNormalizedOhmurl(requestName);
385     if (res.size() != NORMALIZED_OHMURL_ARGS_NUM) {
386         THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, requestName);
387     }
388     CString moduleName = res[NORMALIZED_MODULE_NAME_INDEX];
389     CString bundleName = res[NORMALIZED_BUNDLE_NAME_INDEX];
390     if (!bundleName.empty() && !moduleName.empty()) {
391         baseFileName = ConcatHspFileNameCrossBundle(bundleName, moduleName);
392     } else if (!moduleName.empty()) {
393         baseFileName = ConcatHspFileName(moduleName);
394     } else if (baseFileName.empty()) {
395         // Support multi-module card service
396         baseFileName = thread->GetEcmaVM()->GetAssetPath();
397         // test card service
398     }
399     CString importPath = res[NORMALIZED_IMPORT_PATH_INDEX];
400     CString version = res[NORMALIZED_VERSION_INDEX];
401     return ConcatUnifiedOhmUrl(bundleName, importPath, version);
402 }
403 
404 /*
405  * Before: requestName: ../xxx1/xxx2 || ./b
406  *         recordName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx3 || a
407  * After:  entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx2 || b
408  *         baseFileName: /data/storage/el1/bundle/moduleName/ets/modules.abc || /home/user/src/a
409  */
MakeNewRecord(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & recordName,const CString & requestName)410 CString ModulePathHelper::MakeNewRecord(JSThread *thread, const JSPandaFile *jsPandaFile, CString &baseFileName,
411     const CString &recordName, const CString &requestName)
412 {
413     CString entryPoint;
414     CString moduleRequestName = RemoveSuffix(requestName);
415     size_t pos = moduleRequestName.find(PathHelper::CURRENT_DIREATORY_TAG);
416     if (pos == 0) {
417         moduleRequestName = moduleRequestName.substr(2); // 2 means jump "./"
418     }
419     pos = recordName.rfind(PathHelper::SLASH_TAG);
420     if (pos != CString::npos) {
421         // entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/../xxx1/xxx2
422         entryPoint = recordName.substr(0, pos + 1) + moduleRequestName;
423     } else {
424         entryPoint = moduleRequestName;
425     }
426     // entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx2
427     entryPoint = PathHelper::NormalizePath(entryPoint);
428     entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, entryPoint);
429     if (!entryPoint.empty()) {
430         return entryPoint;
431     }
432     // the package name may have a '.js' suffix, try to parseThirdPartyPackage
433     entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName);
434     if (!entryPoint.empty()) {
435         return entryPoint;
436     }
437     // An exception is thrown when the module cannot be found in bundlePack mode.
438     if (StringHelper::StringStartWith(baseFileName, BUNDLE_INSTALL_PATH) && !jsPandaFile->IsBundlePack() &&
439         !jsPandaFile->HasRecord(entryPoint)) {
440         THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, entryPoint);
441     }
442     // Execute abc locally
443     pos = baseFileName.rfind(PathHelper::SLASH_TAG);
444     if (pos != CString::npos) {
445         baseFileName = baseFileName.substr(0, pos + 1) + moduleRequestName + EXT_NAME_ABC;
446     } else {
447         baseFileName = moduleRequestName + EXT_NAME_ABC;
448     }
449     pos = moduleRequestName.rfind(PathHelper::SLASH_TAG);
450     if (pos != CString::npos) {
451         entryPoint = moduleRequestName.substr(pos + 1);
452     } else {
453         entryPoint = moduleRequestName;
454     }
455     return entryPoint;
456 }
457 
FindOhpmEntryPoint(const JSPandaFile * jsPandaFile,const CString & ohpmPath,const CString & requestName)458 CString ModulePathHelper::FindOhpmEntryPoint(const JSPandaFile *jsPandaFile,
459     const CString& ohpmPath, const CString& requestName)
460 {
461     CVector<CString> vec;
462     StringHelper::SplitString(requestName, vec, 0);
463     ASSERT(vec.size() > 0);
464     size_t maxIndex = vec.size() - 1;
465     CString ohpmKey;
466     size_t index = 0;
467     // first we find the ohpmKey by splicing the requestName
468     while (index <= maxIndex) {
469         CString maybeKey = ohpmPath + PathHelper::SLASH_TAG + StringHelper::JoinString(vec, 0, index);
470         if (jsPandaFile->FindOhmUrlInPF(maybeKey, ohpmKey)) {
471             break;
472         }
473         ++index;
474     }
475     if (ohpmKey.empty()) {
476         return CString();
477     }
478     // second If the ohpmKey is not empty, we will use it to obtain the real entrypoint
479     CString entryPoint;
480     if (index == maxIndex) {
481         // requestName is a packageName
482         entryPoint = jsPandaFile->GetEntryPoint(ohpmKey);
483     } else {
484         // import a specific file or directory
485         ohpmKey = ohpmKey + PathHelper::SLASH_TAG + StringHelper::JoinString(vec, index + 1, maxIndex);
486         entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, ohpmKey);
487     }
488     return entryPoint;
489 }
490 
FindPackageInTopLevelWithNamespace(const JSPandaFile * jsPandaFile,const CString & requestName,const CString & recordName)491 CString ModulePathHelper::FindPackageInTopLevelWithNamespace(const JSPandaFile *jsPandaFile,
492     const CString& requestName, const CString &recordName)
493 {
494     // find in current module <PACKAGE_PATH_SEGMENT>@[moduleName|namespace]/<requestName>
495     CString entryPoint;
496     CString ohpmPath;
497     if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
498         size_t pos = recordName.find(PathHelper::SLASH_TAG);
499         if (pos == CString::npos) {
500             LOG_ECMA(DEBUG) << "wrong recordname : " << recordName;
501             return CString();
502         }
503         ohpmPath = recordName.substr(0, pos);
504         entryPoint = FindOhpmEntryPoint(jsPandaFile, recordName.substr(0, pos), requestName);
505     } else {
506         // recordName: moduleName/xxx/xxx
507         CVector<CString> vec;
508         StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO);
509         if (vec.size() < SEGMENTS_LIMIT_TWO) {
510             LOG_ECMA(DEBUG) << "SplitString filed, please check moduleRequestName";
511             return CString();
512         }
513         CString moduleName = vec[1];
514         // If namespace exists, use namespace as moduleName
515         size_t pos = moduleName.find(PathHelper::NAME_SPACE_TAG);
516         if (pos != CString::npos) {
517             moduleName = moduleName.substr(pos + 1);
518         }
519         ohpmPath = CString(PACKAGE_PATH_SEGMENT) + PathHelper::NAME_SPACE_TAG + moduleName;
520         entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
521         // If haven't find with namespace, then use moduleName
522         if ((pos != CString::npos) && entryPoint.empty()) {
523             moduleName = vec[1].substr(0, pos);
524             ohpmPath = CString(PACKAGE_PATH_SEGMENT) + PathHelper::NAME_SPACE_TAG + moduleName;
525             entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
526         }
527     }
528     if (!entryPoint.empty()) {
529         return entryPoint;
530     }
531     // find in project directory <packagePath>/<requestName>
532     return FindOhpmEntryPoint(jsPandaFile, PACKAGE_PATH_SEGMENT, requestName);
533 }
534 
535 /*
536  * Before: requestName:  requestPkgName
537  *         recordName:   pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
538  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
539  */
ParseOhpmPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName)540 CString ModulePathHelper::ParseOhpmPackage(const JSPandaFile *jsPandaFile,
541     const CString &recordName, const CString &requestName)
542 {
543     CString entryPoint;
544     if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
545         // this way is thirdPartyPackage import ThirdPartyPackage
546         auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName);
547         // packageName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName
548         CString packageName = info.npmPackageName;
549         size_t pos = packageName.rfind(PACKAGE_PATH_SEGMENT);
550         if (pos != CString::npos) {
551             packageName.erase(pos, packageName.size() - pos);
552             // ohpmPath: pkg_modules/.ohpm/pkgName/pkg_modules
553             CString ohpmPath = packageName + PACKAGE_PATH_SEGMENT;
554             // entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
555             entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
556             if (!entryPoint.empty()) {
557                 return entryPoint;
558             }
559         }
560     }
561     // Import packages under the current module or project directory
562     return FindPackageInTopLevelWithNamespace(jsPandaFile, requestName, recordName);
563 }
564 
565 /*
566  * Before: requestName:  requestPkgName
567  *         recordName:   pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
568  *         packagePath:  pkg_modules || node_modules
569  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
570  */
ParseThirdPartyPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName,const CString & packagePath)571 CString ModulePathHelper::ParseThirdPartyPackage(const JSPandaFile *jsPandaFile,
572     const CString &recordName, const CString &requestName, const CString &packagePath)
573 {
574     CString entryPoint;
575     if (StringHelper::StringStartWith(recordName, packagePath)) {
576         auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName);
577         CString packageName = info.npmPackageName; // pkg_modules/.ohpm/pkgName/pkg_modules/pkgName
578         size_t pos = 0;
579         while (true) {
580             CString key = packageName + PathHelper::SLASH_TAG + packagePath + PathHelper::SLASH_TAG + requestName;
581             entryPoint = FindNpmEntryPoint(jsPandaFile, key);
582             if (!entryPoint.empty()) {
583                 return entryPoint;
584             }
585             size_t index = packageName.rfind(packagePath);
586             ASSERT(index > 0);
587             pos = index - 1;
588             if (pos == CString::npos || pos < 0) {
589                 break;
590             }
591             packageName.erase(pos, packageName.size() - pos);
592         }
593     }
594     return FindPackageInTopLevel(jsPandaFile, requestName, packagePath);
595 }
596 
597 /*
598  * Before: requestName:  requestPkgName
599  *         recordName:   pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
600  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
601  */
ParseThirdPartyPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName)602 CString ModulePathHelper::ParseThirdPartyPackage(const JSPandaFile *jsPandaFile,
603     const CString &recordName, const CString &requestName)
604 {
605     // We need to deal with scenarios like this 'json5/' -> 'json5'
606     CString normalizeRequestName = PathHelper::NormalizePath(requestName);
607     CString entryPoint = ParseOhpmPackage(jsPandaFile, recordName, normalizeRequestName);
608     if (!entryPoint.empty()) {
609         return entryPoint;
610     }
611 
612     static CVector<CString> packagePaths = {CString(PACKAGE_PATH_SEGMENT), CString(NPM_PATH_SEGMENT)};
613     // Package compatible with old soft link format
614     for (size_t i = 0; i < packagePaths.size(); ++i) {
615         entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, normalizeRequestName, packagePaths[i]);
616         if (!entryPoint.empty()) {
617             return entryPoint;
618         }
619     }
620     return CString();
621 }
622 
623 /*
624  * Before: dirPath: Undefined
625  *         fileName: Undefined
626  * After:  dirPath: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/
627  *         fileName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/xxx.abc
628  */
ResolveCurrentPath(CString & dirPath,CString & fileName,const JSPandaFile * jsPandaFile)629 void ModulePathHelper::ResolveCurrentPath(CString &dirPath, CString &fileName, const JSPandaFile *jsPandaFile)
630 {
631     ASSERT(jsPandaFile != nullptr);
632     fileName = jsPandaFile->GetJSPandaFileDesc();
633     dirPath = PathHelper::ResolveDirPath(fileName);
634 }
635 
FindNpmEntryPoint(const JSPandaFile * jsPandaFile,const CString & packageEntryPoint)636 CString ModulePathHelper::FindNpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint)
637 {
638     // if we are currently importing a specific file or directory, we will get the entryPoint here
639     CString entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, packageEntryPoint);
640     if (!entryPoint.empty()) {
641         return entryPoint;
642     }
643     // When you come here, must import a packageName
644     return jsPandaFile->GetEntryPoint(packageEntryPoint);
645 }
646 
647 /*
648  * Before: requestName:  requestPkgName
649  *         packagePath:  pkg_modules || node_modules
650  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
651  */
FindPackageInTopLevel(const JSPandaFile * jsPandaFile,const CString & requestName,const CString & packagePath)652 CString ModulePathHelper::FindPackageInTopLevel(const JSPandaFile *jsPandaFile,
653     const CString& requestName, const CString &packagePath)
654 {
655     // we find packagePath/0/xxx or packagePath/1/xxx
656     CString entryPoint;
657     for (size_t level = 0; level <= MAX_PACKAGE_LEVEL; ++level) {
658         CString levelStr = std::to_string(level).c_str();
659         CString key = packagePath + PathHelper::SLASH_TAG + levelStr + PathHelper::SLASH_TAG + requestName;
660         entryPoint = FindNpmEntryPoint(jsPandaFile, key);
661         if (!entryPoint.empty()) {
662             return entryPoint;
663         }
664     }
665     return CString();
666 }
667 
IsImportFile(const CString & moduleRequestName)668 bool ModulePathHelper::IsImportFile(const CString &moduleRequestName)
669 {
670     if (moduleRequestName[0] == PathHelper::POINT_TAG) {
671         return true;
672     }
673     size_t pos = moduleRequestName.rfind(PathHelper::POINT_TAG);
674     if (pos != CString::npos) {
675         CString suffix = moduleRequestName.substr(pos);
676         if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS || suffix == EXT_NAME_JSON) {
677             return true;
678         }
679     }
680     return false;
681 }
682 
683 /*
684  * Before: xxx/xxx.js || xxx/xxx.ts || xxx/xxx.ets ||xxx/xxx.json
685  * After:  xxx/xxx
686  */
RemoveSuffix(const CString & requestName)687 CString ModulePathHelper::RemoveSuffix(const CString &requestName)
688 {
689     CString res = requestName;
690     size_t pos = res.rfind(PathHelper::POINT_TAG);
691     if (pos != CString::npos) {
692         CString suffix = res.substr(pos);
693         if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS ||
694             suffix == EXT_NAME_JSON || suffix == EXT_NAME_MJS) {
695             res.erase(pos, suffix.length());
696         }
697     }
698     return res;
699 }
700 
NeedTranstale(const CString & requestName)701 bool ModulePathHelper::NeedTranstale(const CString &requestName)
702 {
703     if (StringHelper::StringStartWith(requestName, PREFIX_BUNDLE) ||
704         StringHelper::StringStartWith(requestName, PREFIX_PACKAGE) ||
705         requestName[0] == PathHelper::POINT_TAG ||  // ./
706         (requestName[0] == PathHelper::NAME_SPACE_TAG && // @***:
707          requestName.find(PathHelper::COLON_TAG) != CString::npos)) {
708         return false;
709     }
710     return true;
711 }
712 
713 // Adapt dynamic import using expression input, translate include NativeModule/ohpm/hsp/har.
TranstaleExpressionInput(const JSPandaFile * jsPandaFile,CString & requestPath)714 void ModulePathHelper::TranstaleExpressionInput(const JSPandaFile *jsPandaFile, CString &requestPath)
715 {
716     LOG_ECMA(DEBUG) << "Enter Translate OhmUrl for DynamicImport, requestPath: " << requestPath;
717     if (StringHelper::StringStartWith(requestPath, RAW_ARKUIX_PREFIX)) {
718         requestPath = StringHelper::Replace(requestPath, RAW_ARKUIX_PREFIX, REQUIRE_NAPI_OHOS_PREFIX);
719         return;
720     }
721     CString outEntryPoint;
722     // FindOhmUrlInPF: frontend generate mapping in abc,
723     // all we need to do is to find the corresponding mapping result.
724     // EXCEPTION: @ohos. @hms. is translated all by runtime.
725     if (jsPandaFile->FindOhmUrlInPF(requestPath, outEntryPoint)) {
726         // this path for moduleName(xxx or xxx/xxx) -> moduleName/Index;
727         requestPath = outEntryPoint;
728     } else {
729         ParseCrossModuleFile(jsPandaFile, requestPath);
730     }
731     // change origin: @ohos. @hms. -> @ohos: @hms:
732     // change mapping result: @package. @bundle. @xxx. -> @package: @bundle: @xxx:
733     ChangeTag(requestPath);
734 }
735 
736 /*
737  * Before: 1. /data/storage/el1/bundle/moduleName/ets/xxx/xxx.abc
738  *         2. /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
739  * After:  moduleName
740  */
GetModuleNameWithBaseFile(const CString & baseFileName)741 CString ModulePathHelper::GetModuleNameWithBaseFile(const CString &baseFileName)
742 {
743     size_t pos = CString::npos;
744     if (baseFileName.length() > BUNDLE_INSTALL_PATH_LEN &&
745         baseFileName.compare(0, BUNDLE_INSTALL_PATH_LEN, BUNDLE_INSTALL_PATH) == 0) {
746         pos = BUNDLE_INSTALL_PATH_LEN;
747     }
748     CString moduleName;
749     if (pos != CString::npos) {
750         // baseFileName: /data/storage/el1/bundle/moduleName/ets/xxx/xxx.abc
751         pos = baseFileName.find(PathHelper::SLASH_TAG, BUNDLE_INSTALL_PATH_LEN);
752         if (pos == CString::npos) { // LCOV_EXCL_BR_LINE
753             LOG_FULL(FATAL) << "Invalid Ohm url, please check.";
754         }
755         moduleName = baseFileName.substr(BUNDLE_INSTALL_PATH_LEN, pos - BUNDLE_INSTALL_PATH_LEN);
756         // baseFileName /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
757         if (moduleName.find(PathHelper::POINT_STRING_TAG) != CString::npos) {
758             // length of /data/storage/el1/bundle/bundleName/
759             size_t pathLength = BUNDLE_INSTALL_PATH_LEN + moduleName.size() + 1;
760             pos = baseFileName.find(PathHelper::SLASH_TAG, pathLength);
761             moduleName = baseFileName.substr(pathLength, pos - pathLength);
762         }
763     }
764     return moduleName;
765 }
766 
767 /*
768  * Before: ets/xxx/xxx
769  * After:  bundleName/moduleName/ets/xxx/xxx
770  */
TranslateExpressionInputWithEts(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & requestName)771 CString ModulePathHelper::TranslateExpressionInputWithEts(JSThread *thread, const JSPandaFile *jsPandaFile,
772                                                           CString &baseFileName, const CString &requestName)
773 {
774     CString entryPoint;
775     EcmaVM *vm = thread->GetEcmaVM();
776     CString moduleName = GetModuleNameWithBaseFile(baseFileName);
777     entryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + moduleName + PathHelper::SLASH_TAG + requestName;
778     if (!jsPandaFile->HasRecord(entryPoint)) {
779         return CString();
780     }
781     return entryPoint;
782 }
783 
784 /*
785  * input requestPath: moduleName/src/main/xxx/xxx/xxx
786  *                    moduleName/xxx/xxx
787  * moduleName : singleLevelName or twoLevelName
788  * output requestPath: @bundle.bundleName/moduleName/xxx/xxx/xxx
789  *                     @bundle.bundleName/moduleName/xxx/xxx
790  */
ParseCrossModuleFile(const JSPandaFile * jsPandaFile,CString & requestPath)791 void ModulePathHelper::ParseCrossModuleFile(const JSPandaFile *jsPandaFile, CString &requestPath)
792 {
793     size_t pos = requestPath.find(PathHelper::SLASH_TAG);
794     if (pos == CString::npos) {
795         return;
796     }
797     CString moduleName = requestPath.substr(0, pos);
798     CString outEntryPoint;
799     // try get mapped module path by single level moduleName.
800     bool isModuleName = jsPandaFile->FindOhmUrlInPF(moduleName, outEntryPoint);
801     if (!isModuleName) {
802         // retry get mapped module path by two level moduleName
803         pos = requestPath.find(PathHelper::SLASH_TAG, pos + 1);
804         if (pos == CString::npos) {
805             return;
806         }
807         moduleName = requestPath.substr(0, pos);
808         isModuleName = jsPandaFile->FindOhmUrlInPF(moduleName, outEntryPoint);
809     }
810     if (isModuleName) {
811         // outEntryPoint: @bundle.bundleName/moduleName/Index
812         CString relativePath = requestPath.substr(pos);
813         // get rid of Index, get pure perfix(@bundle.bundleName/moduleName).
814         size_t index = outEntryPoint.rfind(PathHelper::SLASH_TAG);
815         // get rid of src/main. Concat perfix and input relative path.
816         if (relativePath.find(PHYCICAL_FILE_PATH, 0) == 0) {
817             requestPath = outEntryPoint.substr(0, index) + PathHelper::SLASH_TAG +
818                 requestPath.substr(pos + PHYCICAL_FILE_PATH_LEN);
819             return;
820         }
821         requestPath = outEntryPoint.substr(0, index) + requestPath.substr(pos);
822     }
823 }
824 
ParseFileNameToVMAName(const CString & filename)825 CString ModulePathHelper::ParseFileNameToVMAName(const CString &filename)
826 {
827     CString tag = VMA_NAME_ARKTS_CODE;
828     size_t pos = CString::npos;
829     if (filename.empty()) {
830         return tag;
831     }
832 
833     if (filename.find(EXT_NAME_JS) != CString::npos) {
834         pos = filename.find(EXT_NAME_Z_SO);
835         if (pos == CString::npos) {
836             return tag;
837         }
838         CString moduleName = filename.substr(0, pos);
839         pos = moduleName.rfind(PathHelper::POINT_TAG);
840         if (pos == CString::npos) {
841             return tag + PathHelper::COLON_TAG + filename;
842         }
843         CString realModuleName = moduleName.substr(pos + 1);
844         CString realFileName = realModuleName;
845         std::transform(realFileName.begin(), realFileName.end(), realFileName.begin(), ::tolower);
846         CString file = PREFIX_LIB + realFileName + EXT_NAME_Z_SO + PathHelper::SLASH_TAG + realModuleName + EXT_NAME_JS;
847         return tag + PathHelper::COLON_TAG + file;
848     }
849 
850     if (filename.find(EXT_NAME_ABC) != CString::npos) {
851         pos = filename.find(BUNDLE_INSTALL_PATH);
852         if (pos == CString::npos) {
853             return tag + PathHelper::COLON_TAG + filename;
854         }
855         CString file = filename.substr(BUNDLE_INSTALL_PATH_LEN);
856         return tag + PathHelper::COLON_TAG + file;
857     }
858 
859     return tag;
860 }
861 
GetPkgContextInfoListElements(EcmaVM * vm,CString & moduleName,CString & packageName)862 CVector<CString> ModulePathHelper::GetPkgContextInfoListElements(EcmaVM *vm, CString &moduleName,
863                                                                  CString &packageName)
864 {
865     CVector<CString> resultList;
866     if (packageName.size() == 0) {
867         return resultList;
868     }
869     CMap<CString, CMap<CString, CVector<CString>>> pkgContextList = vm->GetPkgContextInfoLit();
870     if (pkgContextList.find(moduleName) == pkgContextList.end()) {
871         return resultList;
872     }
873     CMap<CString, CVector<CString>> pkgList = pkgContextList[moduleName];
874     if (pkgList.find(packageName) == pkgList.end()) {
875         return resultList;
876     }
877     resultList = pkgList[packageName];
878     return resultList;
879 }
880 
ConcatImportFileNormalizedOhmurl(const CString & recordPath,const CString & requestName,const CString & version)881 CString ModulePathHelper::ConcatImportFileNormalizedOhmurl(const CString &recordPath, const CString &requestName,
882     const CString &version)
883 {
884     return recordPath + requestName + PathHelper::NORMALIZED_OHMURL_TAG + version;
885 }
886 
ConcatNativeSoNormalizedOhmurl(const CString & moduleName,const CString & bundleName,const CString & pkgName,const CString & version)887 CString ModulePathHelper::ConcatNativeSoNormalizedOhmurl(const CString &moduleName, const CString &bundleName,
888     const CString &pkgName, const CString &version)
889 {
890     CString prefix = PREFIX_NORMALIZED_SO;
891     return prefix + PathHelper::NORMALIZED_OHMURL_TAG + moduleName + PathHelper::NORMALIZED_OHMURL_TAG +
892         bundleName + PathHelper::NORMALIZED_OHMURL_TAG + pkgName + PathHelper::NORMALIZED_OHMURL_TAG + version;
893 }
894 
ConcatNotSoNormalizedOhmurl(const CString & moduleName,const CString & bundleName,const CString & pkgName,const CString & entryPath,const CString & version)895 CString ModulePathHelper::ConcatNotSoNormalizedOhmurl(const CString &moduleName, const CString &bundleName,
896     const CString &pkgName, const CString &entryPath, const CString &version)
897 {
898     CString prefix = PREFIX_NORMALIZED_NOT_SO;
899     return prefix + PathHelper::NORMALIZED_OHMURL_TAG + moduleName + PathHelper::NORMALIZED_OHMURL_TAG +
900         bundleName + PathHelper::NORMALIZED_OHMURL_TAG + pkgName + PathHelper::SLASH_TAG + entryPath +
901         PathHelper::NORMALIZED_OHMURL_TAG + version;
902 }
903 
NeedTranslateToNormalized(const CString & requestName)904 bool ModulePathHelper::NeedTranslateToNormalized(const CString &requestName)
905 {
906     // if start with @normalized:xxx @native:xxx.xxx @ohos:xxx
907     // no translation is required
908     if (StringHelper::StringStartWith(requestName, PREFIX_NORMALIZED) ||
909         (requestName[0] == PathHelper::NAME_SPACE_TAG &&
910          requestName.find(PathHelper::COLON_TAG) != CString::npos)) {
911             return false;
912     }
913     return true;
914 }
915 
TranslateExpressionToNormalized(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & recordName,CString & requestPath)916 CString ModulePathHelper::TranslateExpressionToNormalized(JSThread *thread, const JSPandaFile *jsPandaFile,
917     [[maybe_unused]] CString &baseFileName, const CString &recordName, CString &requestPath)
918 {
919     if (!NeedTranslateToNormalized(requestPath)) {
920         return requestPath;
921     }
922     if (StringHelper::StringStartWith(requestPath, RAW_ARKUIX_PREFIX)) {
923         return StringHelper::Replace(requestPath, RAW_ARKUIX_PREFIX, REQUIRE_NAPI_OHOS_PREFIX);
924     }
925     EcmaVM *vm = thread->GetEcmaVM();
926     CString inputPath = requestPath;
927     if (IsImportFile(requestPath)) {
928         CString entryPoint = ConcatImportFileNormalizedOhmurlWithRecordName(thread, jsPandaFile, baseFileName,
929             recordName, requestPath);
930         if (entryPoint.empty()) {
931             THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, inputPath, recordName, requestPath);
932         }
933     } else if (StringHelper::StringStartWith(requestPath, PREFIX_ETS)) {
934         size_t pos = recordName.find(PREFIX_ETS);
935         if (pos != CString::npos) {
936             requestPath = ConcatImportFileNormalizedOhmurl(recordName.substr(0, pos), requestPath);
937         }
938         if (!jsPandaFile->HasRecord(requestPath)) {
939             THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, inputPath, recordName, requestPath);
940         }
941     } else {
942         ConcatOtherNormalizedOhmurl(vm, jsPandaFile, baseFileName, requestPath);
943     }
944     return requestPath;
945 }
946 
947 /*
948  * Before: requestPath: 1. @ohos.xxx
949  *                      2. har or har/xxx/xxx
950  *                      3. hsp or hsp/xxx/xxx
951  *                      4. libentry.so
952  * After:  requestPath: 1. @ohos:xxx or @native:xxx.xxx
953  *                      2. @normalized:N&moduleName&bundleName&entryPath&version
954  *                      3. @normalized:N&moduleName&bundleName&entryPath&
955  *                      4. @normalized:Y&&bundleName&entryPath&version
956  */
ConcatOtherNormalizedOhmurl(EcmaVM * vm,const JSPandaFile * jsPandaFile,CString & baseFileName,CString & requestPath)957 void ModulePathHelper::ConcatOtherNormalizedOhmurl(EcmaVM *vm, const JSPandaFile *jsPandaFile,
958     [[maybe_unused]] CString &baseFileName, CString &requestPath)
959 {
960     CString entryPath;
961     CString currentModuleName = GetModuleNameWithBaseFile(baseFileName);
962     CString pkgName = vm->GetPkgNameWithAlias(requestPath);
963     CVector<CString> data = GetPkgContextInfoListElements(vm, currentModuleName, pkgName);
964     if (data.size() != 0) {
965         requestPath = ConcatNormalizedOhmurlWithData(data, pkgName, entryPath);
966         return;
967     }
968     // When requestName contains '/', it is considered to be a file path.
969     CString result;
970     size_t filePathPos = requestPath.find(PathHelper::SLASH_TAG);
971     if (filePathPos != CString::npos) {
972         result = ConcatOtherNormalizedOhmurlWithFilePath(vm, filePathPos, currentModuleName, requestPath);
973         // Try to get the PkgContextInfo by two levels alias
974         if (result.size() == 0) {
975             filePathPos = requestPath.find(PathHelper::SLASH_TAG, filePathPos + 1);
976             if (filePathPos != CString::npos) {
977                 result = ConcatOtherNormalizedOhmurlWithFilePath(vm, filePathPos, currentModuleName, requestPath);
978             }
979         }
980     }
981     if (result.size() == 0) {
982         CString outEntryPoint;
983         if (jsPandaFile->FindOhmUrlInPF(requestPath, outEntryPoint)) {
984             requestPath = outEntryPoint;
985         }
986         ChangeTag(requestPath);
987         return;
988     }
989     requestPath = result;
990 }
991 
ConcatOtherNormalizedOhmurlWithFilePath(EcmaVM * vm,size_t filePathPos,CString & moduleName,const CString & requestPath)992 CString ModulePathHelper::ConcatOtherNormalizedOhmurlWithFilePath(EcmaVM *vm, size_t filePathPos,
993     CString &moduleName, const CString &requestPath)
994 {
995     CString result;
996     CString alias = requestPath.substr(0, filePathPos);
997     CString entryPath = requestPath.substr(filePathPos + 1);
998     CString pkgName = vm->GetPkgNameWithAlias(alias);
999     CVector<CString> data = GetPkgContextInfoListElements(vm, moduleName, pkgName);
1000     if (data.size() != 0) {
1001         result = ConcatNormalizedOhmurlWithData(data, pkgName, entryPath);
1002     }
1003     return result;
1004 }
1005 
ConcatNormalizedOhmurlWithData(CVector<CString> & data,CString & pkgName,CString & entryPath)1006 CString ModulePathHelper::ConcatNormalizedOhmurlWithData(CVector<CString> &data, CString &pkgName, CString &entryPath)
1007 {
1008     CString bundleName = data[PKGINFO_BUDNLE_NAME_INDEX];
1009     CString moduleName = data[PKGINFO_MODULE_NAME_INDEX];
1010     CString version = data[PKGINFO_VERSION_INDEX];
1011     if (entryPath.size() == 0) {
1012         entryPath = data[PKGINFO_ENTRY_PATH_INDEX];
1013     }
1014     CString isSO = data[PKGINFO_IS_SO_INDEX];
1015     size_t pos = entryPath.find(PathHelper::CURRENT_DIREATORY_TAG);
1016     if (pos == 0) {
1017         entryPath = entryPath.substr(CURRENT_DIREATORY_TAG_LEN);
1018     }
1019     if (isSO == TRUE_FLAG) {
1020         return ConcatNativeSoNormalizedOhmurl(moduleName, bundleName, pkgName, version);
1021     } else {
1022         entryPath = RemoveSuffix(entryPath);
1023         return ConcatNotSoNormalizedOhmurl(moduleName, bundleName, pkgName, entryPath, version);
1024     }
1025 }
1026 
TranslateNapiFileRequestPath(JSThread * thread,const CString & modulePath,const CString & requestName)1027 CString ModulePathHelper::TranslateNapiFileRequestPath(JSThread *thread, const CString &modulePath,
1028     const CString &requestName)
1029 {
1030     if (thread->GetEcmaVM()->IsNormalizedOhmUrlPack()) {
1031         CString moduleName = GetModuleNameWithPath(modulePath);
1032         return PathHelper::NORMALIZED_OHMURL_TAG + moduleName + PHYCICAL_FILE_PATH + PathHelper::SLASH_TAG +
1033             requestName + PathHelper::NORMALIZED_OHMURL_TAG;
1034     } else {
1035         return modulePath + PathHelper::SLASH_TAG + requestName;
1036     }
1037 }
1038 
SplitNormalizedOhmurl(const CString & ohmurl)1039 CVector<CString> ModulePathHelper::SplitNormalizedOhmurl(const CString &ohmurl)
1040 {
1041     CVector<CString> res;
1042     size_t start = 0;
1043     size_t pos = ohmurl.find(PathHelper::NORMALIZED_OHMURL_TAG);
1044     while (pos != CString::npos) {
1045         CString element = ohmurl.substr(start, pos - start);
1046         res.emplace_back(element);
1047         start = pos + 1;
1048         pos = ohmurl.find(PathHelper::NORMALIZED_OHMURL_TAG, start);
1049     }
1050     CString tail = ohmurl.substr(start);
1051     res.emplace_back(tail);
1052     return res;
1053 }
1054 
SplitNormalizedRecordName(const CString & recordName)1055 CVector<CString> ModulePathHelper::SplitNormalizedRecordName(const CString &recordName)
1056 {
1057     CVector<CString> res(NORMALIZED_OHMURL_ARGS_NUM);
1058     int index = NORMALIZED_OHMURL_ARGS_NUM - 1;
1059     CString temp;
1060     int endIndex = static_cast<int>(recordName.size()) - 1;
1061     for (int i = endIndex; i >= 0; i--) {
1062         char element = recordName[i];
1063         if (element == PathHelper::NORMALIZED_OHMURL_TAG) {
1064             res[index] = temp;
1065             index--;
1066             temp = "";
1067             continue;
1068         }
1069         temp = element + temp;
1070     }
1071     if (temp.size()) {
1072         res[index] = temp;
1073     }
1074     return res;
1075 }
1076 
1077 /*
1078  * Before: 1. bundleName/moduleName/xxx/xxx
1079            2. bunldeName&moduleName/xxx/xxx&
1080  * After:  bundleName
1081  */
GetBundleNameWithRecordName(EcmaVM * vm,const CString & recordName)1082 CString ModulePathHelper::GetBundleNameWithRecordName(EcmaVM *vm, const CString &recordName)
1083 {
1084     CString bundleName;
1085     if (vm->IsNormalizedOhmUrlPack()) {
1086         CVector<CString> res = ModulePathHelper::SplitNormalizedRecordName(recordName);
1087         bundleName = res[ModulePathHelper::NORMALIZED_BUNDLE_NAME_INDEX];
1088         if (bundleName.size() == 0) {
1089             bundleName = vm->GetBundleName();
1090         }
1091     } else {
1092         size_t pos = recordName.find(PathHelper::SLASH_TAG);
1093         bundleName = recordName.substr(0, pos);
1094     }
1095     return bundleName;
1096 }
1097 
1098 // this function convert for ESModule name string(Utf8)
Utf8ConvertToString(JSTaggedValue str)1099 CString ModulePathHelper::Utf8ConvertToString(JSTaggedValue str)
1100 {
1101     return EcmaStringAccessor(str).Utf8ConvertToString();
1102 }
1103 }  // namespace panda::ecmascript