• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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     CString entryPoint;
25     if (StringHelper::StringStartWith(requestName, PREFIX_BUNDLE)) {
26         // requestName: @bundle:bundleName/moduleName@namespace/ets/xxx/xxx
27         entryPoint = ParsePrefixBundle(thread, jsPandaFile, baseFileName, requestName, recordName);
28     } else if (StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) {
29         // requestName: @package:pkg_modules@namespace/xxx/Index
30         entryPoint = requestName.substr(PREFIX_PACKAGE_LEN);
31     } else if (IsImportFile(requestName)) {
32         // this branch save for require/dynamic import/old version sdk
33         // load a relative pathName.
34         // requestName: ./ || ./xxx/xxx.js || ../xxx/xxx.js || ./xxx/xxx
35         entryPoint = MakeNewRecord(jsPandaFile, baseFileName, recordName, requestName);
36     } else {
37         // this branch save for require/dynamic import/old version sdk
38         // requestName: requestPkgName
39         entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName);
40     }
41     if (entryPoint.empty() && thread->GetEcmaVM()->EnableReportModuleResolvingFailure()) {
42         LOG_ECMA(ERROR) << "Failed to resolve the requested entryPoint. baseFileName : '" << baseFileName <<
43             "'. RecordName : '" <<  recordName << "'. RequestName : '" <<  requestName << "'.";
44         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45         CString msg = "failed to load module'" + requestName + "' which imported by '" +
46             recordName + "'. Please check the target path.";
47         JSTaggedValue error = factory->GetJSError(ErrorType::REFERENCE_ERROR, msg.c_str()).GetTaggedValue();
48         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, entryPoint);
49     }
50     LOG_ECMA(DEBUG) << "Concated baseFileName : '" << baseFileName <<
51         "'. EntryPoint : '" <<  entryPoint << "'.";
52     return entryPoint;
53 }
54 
55 /*
56  * Before: inputFileName: 1. /data/storage/el1/bundle/moduleName/ets/xxx/xxx.abc
57                           2. @bundle:bundleName/moduleName/ets/xxx/xxx.abc
58                           3. moduleName/ets/xxx/xxx.abc
59                           4. .test/xxx/xxx.abc
60                           5. xxx/xxx.abc
61  * After:  outBaseFileName: /data/storage/el1/bundle/moduleName/ets/modules.abc
62  *         outEntryPoint: bundleName/moduleName/ets/xxx/xxx
63  */
ParseOhmUrl(EcmaVM * vm,const CString & inputFileName,CString & outBaseFileName,CString & outEntryPoint)64 void ModulePathHelper::ParseOhmUrl(EcmaVM *vm, const CString &inputFileName,
65     CString &outBaseFileName, CString &outEntryPoint)
66 {
67     CString bundleInstallName(BUNDLE_INSTALL_PATH);
68     size_t startStrLen = bundleInstallName.length();
69     size_t pos = CString::npos;
70 
71     if (inputFileName.length() > startStrLen && inputFileName.compare(0, startStrLen, bundleInstallName) == 0) {
72         pos = startStrLen;
73     }
74     if (pos != CString::npos) {
75         // inputFileName: /data/storage/el1/bundle/moduleName/ets/xxx/xxx.abc
76         pos = inputFileName.find(PathHelper::SLASH_TAG, startStrLen);
77         if (pos == CString::npos) {
78             LOG_FULL(FATAL) << "Invalid Ohm url, please check.";
79         }
80         CString moduleName = inputFileName.substr(startStrLen, pos - startStrLen);
81         outBaseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
82         outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + inputFileName.substr(startStrLen);
83     } else {
84         // Temporarily handle the relative path sent by arkui
85         // inputFileName: @bundle:bundleName/moduleName/ets/xxx/xxx.abc
86         if (StringHelper::StringStartWith(inputFileName, PREFIX_BUNDLE)) {
87             outEntryPoint = inputFileName.substr(PREFIX_BUNDLE_LEN);
88             outBaseFileName = ParseUrl(vm, outEntryPoint);
89         } else {
90 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
91             // inputFileName: moduleName/ets/xxx/xxx.abc
92             outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + inputFileName;
93 #else
94             // if the inputFileName starts with '.test', the preview test page is started.
95             // in this case, the path ets does not need to be combined.
96             // inputFileName: .test/xxx/xxx.abc
97             if (StringHelper::StringStartWith(inputFileName, PREVIER_TEST_DIR)) {
98                 outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + vm->GetModuleName() +
99                                 PathHelper::SLASH_TAG + inputFileName;
100             } else {
101                 // inputFileName: xxx/xxx.abc
102                 outEntryPoint = vm->GetBundleName() + PathHelper::SLASH_TAG + vm->GetModuleName() +
103                                 MODULE_DEFAULE_ETS + inputFileName;
104             }
105 #endif
106         }
107     }
108     if (StringHelper::StringEndWith(outEntryPoint, EXT_NAME_ABC)) {
109         outEntryPoint.erase(outEntryPoint.length() - EXT_NAME_ABC_LEN, EXT_NAME_ABC_LEN);
110     }
111 }
112 
113 /*
114  * Before: recordName: bundleName/moduleName@namespace/moduleName/xxx/xxx.abc
115  * After: Intra-application cross hap:   /data/storage/el1/bundle/bundleName/ets/modules.abc
116  *        Cross-application:             /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
117  */
ParseUrl(EcmaVM * vm,const CString & recordName)118 CString ModulePathHelper::ParseUrl(EcmaVM *vm, const CString &recordName)
119 {
120     CVector<CString> vec;
121     StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO);
122     if (vec.size() < SEGMENTS_LIMIT_TWO) {
123         LOG_ECMA(DEBUG) << "ParseUrl SplitString filed, please check Url" << recordName;
124         return CString();
125     }
126     CString bundleName = vec[0];
127     CString moduleName = vec[1];
128     PathHelper::DeleteNamespace(moduleName);
129 
130     CString baseFileName;
131     if (bundleName != vm->GetBundleName()) {
132         // Cross-application
133         baseFileName = BUNDLE_INSTALL_PATH + bundleName + PathHelper::SLASH_TAG + moduleName +
134                        PathHelper::SLASH_TAG + moduleName + MERGE_ABC_ETS_MODULES;
135     } else {
136         // Intra-application cross hap
137         baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
138     }
139     return baseFileName;
140 }
141 
142 /*
143  * Before: moduleRequestName: @bundle:bundleName/moduleName@namespace/ets/xxx
144  * After:  baseFileName: 1./data/storage/el1/bundle/bundleName/ets/modules.abc
145  *                       2./data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
146  *         entryPoint:   bundleName/moduleName@namespace/ets/xxx
147  */
ParsePrefixBundle(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,CString moduleRequestName,CString recordName)148 CString ModulePathHelper::ParsePrefixBundle(JSThread *thread, const JSPandaFile *jsPandaFile,
149     [[maybe_unused]] CString &baseFileName, CString moduleRequestName, [[maybe_unused]] CString recordName)
150 {
151     EcmaVM *vm = thread->GetEcmaVM();
152     moduleRequestName = moduleRequestName.substr(PREFIX_BUNDLE_LEN);
153     CString entryPoint = moduleRequestName;
154     if (jsPandaFile->IsRecordWithBundleName()) {
155         CVector<CString> vec;
156         StringHelper::SplitString(moduleRequestName, vec, 0, SEGMENTS_LIMIT_TWO);
157         if (vec.size() < SEGMENTS_LIMIT_TWO) {
158             LOG_ECMA(INFO) << "SplitString filed, please check moduleRequestName";
159             return CString();
160         }
161         CString bundleName = vec[0];
162         CString moduleName = vec[1];
163         PathHelper::DeleteNamespace(moduleName);
164 
165 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
166         if (bundleName != vm->GetBundleName()) {
167             baseFileName = BUNDLE_INSTALL_PATH + bundleName + PathHelper::SLASH_TAG + moduleName +
168                            PathHelper::SLASH_TAG + moduleName + MERGE_ABC_ETS_MODULES;
169         } else if (moduleName != vm->GetModuleName()) {
170             baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES;
171         } else {
172             // Support multi-module card service
173             baseFileName = vm->GetAssetPath();
174         }
175 #else
176         CVector<CString> currentVec;
177         StringHelper::SplitString(recordName, currentVec, 0, SEGMENTS_LIMIT_TWO);
178         if (currentVec.size() < SEGMENTS_LIMIT_TWO) {
179             LOG_ECMA(INFO) << "SplitString filed, please check recordName";
180             return CString();
181         }
182         CString currentModuleName = currentVec[1];
183         PathHelper::DeleteNamespace(currentModuleName);
184         if (bundleName != vm->GetBundleName() || moduleName != currentModuleName) {
185             entryPoint = PREVIEW_OF_ACROSS_HAP_FLAG;
186             if (vm->EnableReportModuleResolvingFailure()) {
187                 LOG_NO_TAG(ERROR) << "[ArkRuntime Log] Importing shared package is not supported in the Previewer.";
188             }
189         }
190 #endif
191     } else {
192         PathHelper::AdaptOldIsaRecord(entryPoint);
193     }
194     return entryPoint;
195 }
196 
197 /*
198  * Before: requestName: ../xxx1/xxx2 || ./b
199  *         recordName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx3 || a
200  * After:  entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx2 || b
201  *         baseFileName: /data/storage/el1/bundle/moduleName/ets/modules.abc || /home/user/src/a
202  */
MakeNewRecord(const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & recordName,const CString & requestName)203 CString ModulePathHelper::MakeNewRecord(const JSPandaFile *jsPandaFile, CString &baseFileName,
204     const CString &recordName, const CString &requestName)
205 {
206     CString entryPoint;
207     CString moduleRequestName = RemoveSuffix(requestName);
208     size_t pos = moduleRequestName.find(PathHelper::CURRENT_DIREATORY_TAG);
209     if (pos == 0) {
210         moduleRequestName = moduleRequestName.substr(2); // 2 means jump "./"
211     }
212     pos = recordName.rfind(PathHelper::SLASH_TAG);
213     if (pos != CString::npos) {
214         // entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/../xxx1/xxx2
215         entryPoint = recordName.substr(0, pos + 1) + moduleRequestName;
216     } else {
217         entryPoint = moduleRequestName;
218     }
219     // entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx2
220     entryPoint = PathHelper::NormalizePath(entryPoint);
221     entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, entryPoint);
222     if (!entryPoint.empty()) {
223         return entryPoint;
224     }
225     // the package name may have a '.js' suffix, try to parseThirdPartyPackage
226     entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName);
227     if (!entryPoint.empty()) {
228         return entryPoint;
229     }
230     // Execute abc locally
231     pos = baseFileName.rfind(PathHelper::SLASH_TAG);
232     if (pos != CString::npos) {
233         baseFileName = baseFileName.substr(0, pos + 1) + moduleRequestName + EXT_NAME_ABC;
234     } else {
235         baseFileName = moduleRequestName + EXT_NAME_ABC;
236     }
237     pos = moduleRequestName.rfind(PathHelper::SLASH_TAG);
238     if (pos != CString::npos) {
239         entryPoint = moduleRequestName.substr(pos + 1);
240     } else {
241         entryPoint = moduleRequestName;
242     }
243     return entryPoint;
244 }
245 
246 /*
247  * Before: ohpmPath:      pkg_modules/.ohpm/pkgName/pkg_modules
248  *         requestName:   requestPkgName
249  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
250  */
FindOhpmEntryPoint(const JSPandaFile * jsPandaFile,const CString & ohpmPath,const CString & requestName)251 CString ModulePathHelper::FindOhpmEntryPoint(const JSPandaFile *jsPandaFile,
252     const CString& ohpmPath, const CString& requestName)
253 {
254     CVector<CString> vec;
255     StringHelper::SplitString(requestName, vec, 0);
256     size_t maxIndex = vec.size() - 1;
257     CString ohpmKey;
258     size_t index = 0;
259     // first we find the ohpmKey by splicing the requestName
260     while (index <= maxIndex) {
261         // maybeKey: pkg_modules/.ohpm/pkgName/pkg_modules/requestPkgName
262         CString maybeKey = ohpmPath + PathHelper::SLASH_TAG + StringHelper::JoinString(vec, 0, index);
263         // ohpmKey: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName
264         ohpmKey = jsPandaFile->GetNpmEntries(maybeKey);
265         if (!ohpmKey.empty()) {
266             break;
267         }
268         ++index;
269     }
270     if (ohpmKey.empty()) {
271         return CString();
272     }
273     // second If the ohpmKey is not empty, we will use it to obtain the real entrypoint
274     CString entryPoint;
275     if (index == maxIndex) {
276         // requestName is a packageName
277         // entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
278         entryPoint = jsPandaFile->GetEntryPoint(ohpmKey);
279     } else {
280         // import a specific file or directory
281         ohpmKey = ohpmKey + PathHelper::SLASH_TAG + StringHelper::JoinString(vec, index + 1, maxIndex);
282         entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, ohpmKey);
283     }
284     return entryPoint;
285 }
286 
FindPackageInTopLevelWithNamespace(const JSPandaFile * jsPandaFile,const CString & requestName,const CString & recordName)287 CString ModulePathHelper::FindPackageInTopLevelWithNamespace(const JSPandaFile *jsPandaFile,
288     const CString& requestName, const CString &recordName)
289 {
290     // find in current module <PACKAGE_PATH_SEGMENT>@[moduleName|namespace]/<requestName>
291     CString entryPoint;
292     CString ohpmPath;
293     if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
294         size_t pos = recordName.find(PathHelper::SLASH_TAG);
295         if (pos == CString::npos) {
296             LOG_ECMA(DEBUG) << "wrong recordname : " << recordName;
297             return CString();
298         }
299         ohpmPath = recordName.substr(0, pos);
300         entryPoint = FindOhpmEntryPoint(jsPandaFile, recordName.substr(0, pos), requestName);
301     } else {
302         CVector<CString> vec;
303         StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO);
304         if (vec.size() < SEGMENTS_LIMIT_TWO) {
305             LOG_ECMA(DEBUG) << "SplitString filed, please check moduleRequestName";
306             return CString();
307         }
308         CString moduleName = vec[1];
309         // If namespace exists, use namespace as moduleName
310         size_t pos = moduleName.find(PathHelper::NAME_SPACE_TAG);
311         if (pos != CString::npos) {
312             moduleName = moduleName.substr(pos + 1);
313         }
314         ohpmPath = CString(PACKAGE_PATH_SEGMENT) + PathHelper::NAME_SPACE_TAG + moduleName;
315         entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
316     }
317     if (!entryPoint.empty()) {
318         return entryPoint;
319     }
320     // find in project directory <packagePath>/<requestName>
321     return FindOhpmEntryPoint(jsPandaFile, PACKAGE_PATH_SEGMENT, requestName);
322 }
323 
324 /*
325  * Before: requestName:  requestPkgName
326  *         recordName:   pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
327  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
328  */
ParseOhpmPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName)329 CString ModulePathHelper::ParseOhpmPackage(const JSPandaFile *jsPandaFile,
330     const CString &recordName, const CString &requestName)
331 {
332     CString entryPoint;
333     if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
334         // this way is thirdPartyPackage import ThirdPartyPackage
335         auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName);
336         // packageName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName
337         CString packageName = info.npmPackageName;
338         size_t pos = packageName.rfind(PACKAGE_PATH_SEGMENT);
339         if (pos != CString::npos) {
340             packageName.erase(pos, packageName.size() - pos);
341             // ohpmPath: pkg_modules/.ohpm/pkgName/pkg_modules
342             CString ohpmPath = packageName + PACKAGE_PATH_SEGMENT;
343             // entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
344             entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
345             if (!entryPoint.empty()) {
346                 return entryPoint;
347             }
348         }
349     }
350     // Import packages under the current module or project directory
351     return FindPackageInTopLevelWithNamespace(jsPandaFile, requestName, recordName);
352 }
353 
354 /*
355  * Before: requestName:  requestPkgName
356  *         recordName:   pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
357  *         packagePath:  pkg_modules || node_modules
358  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
359  */
ParseThirdPartyPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName,const CString & packagePath)360 CString ModulePathHelper::ParseThirdPartyPackage(const JSPandaFile *jsPandaFile,
361     const CString &recordName, const CString &requestName, const CString &packagePath)
362 {
363     CString entryPoint;
364     if (StringHelper::StringStartWith(recordName, packagePath)) {
365         auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName);
366         CString packageName = info.npmPackageName; // pkg_modules/.ohpm/pkgName/pkg_modules/pkgName
367         size_t pos = 0;
368         while (true) {
369             CString key = packageName + PathHelper::SLASH_TAG + packagePath + PathHelper::SLASH_TAG + requestName;
370             entryPoint = FindNpmEntryPoint(jsPandaFile, key);
371             if (!entryPoint.empty()) {
372                 return entryPoint;
373             }
374             pos = packageName.rfind(packagePath) - 1;
375             if (pos == CString::npos || pos < 0) {
376                 break;
377             }
378             packageName.erase(pos, packageName.size() - pos);
379         }
380     }
381     return FindPackageInTopLevel(jsPandaFile, requestName, packagePath);
382 }
383 
384 /*
385  * Before: requestName:  requestPkgName
386  *         recordName:   pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
387  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
388  */
ParseThirdPartyPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName)389 CString ModulePathHelper::ParseThirdPartyPackage(const JSPandaFile *jsPandaFile,
390     const CString &recordName, const CString &requestName)
391 {
392     // We need to deal with scenarios like this 'json5/' -> 'json5'
393     CString normalizeRequestName = PathHelper::NormalizePath(requestName);
394     CString entryPoint = ParseOhpmPackage(jsPandaFile, recordName, normalizeRequestName);
395     if (!entryPoint.empty()) {
396         return entryPoint;
397     }
398 
399     static CVector<CString> packagePaths = {CString(PACKAGE_PATH_SEGMENT), CString(NPM_PATH_SEGMENT)};
400     // Package compatible with old soft link format
401     for (size_t i = 0; i < packagePaths.size(); ++i) {
402         entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, normalizeRequestName, packagePaths[i]);
403         if (!entryPoint.empty()) {
404             return entryPoint;
405         }
406     }
407     return CString();
408 }
409 
410 /*
411  * Before: dirPath: Undefined
412  *         fileName: Undefined
413  * After:  dirPath: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/
414  *         fileName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/xxx.abc
415  */
ResolveCurrentPath(JSThread * thread,JSMutableHandle<JSTaggedValue> & dirPath,JSMutableHandle<JSTaggedValue> & fileName,const JSPandaFile * jsPandaFile)416 void ModulePathHelper::ResolveCurrentPath(JSThread *thread, JSMutableHandle<JSTaggedValue> &dirPath,
417     JSMutableHandle<JSTaggedValue> &fileName, const JSPandaFile *jsPandaFile)
418 {
419     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
420     CString fullName = jsPandaFile->GetJSPandaFileDesc();
421     JSHandle<EcmaString> dirPathName = PathHelper::ResolveDirPath(thread, fullName);
422     dirPath.Update(dirPathName.GetTaggedValue());
423 
424     // Get filename from JSPandaFile
425     JSHandle<EcmaString> cbFileName = factory->NewFromUtf8(fullName);
426     fileName.Update(cbFileName.GetTaggedValue());
427 }
428 
FindNpmEntryPoint(const JSPandaFile * jsPandaFile,const CString & packageEntryPoint)429 CString ModulePathHelper::FindNpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint)
430 {
431     // if we are currently importing a specific file or directory, we will get the entryPoint here
432     CString entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, packageEntryPoint);
433     if (!entryPoint.empty()) {
434         return entryPoint;
435     }
436     // When you come here, must import a packageName
437     return jsPandaFile->GetEntryPoint(packageEntryPoint);
438 }
439 
440 /*
441  * Before: requestName:  requestPkgName
442  *         packagePath:  pkg_modules || node_modules
443  * After:  entryPoint:   pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
444  */
FindPackageInTopLevel(const JSPandaFile * jsPandaFile,const CString & requestName,const CString & packagePath)445 CString ModulePathHelper::FindPackageInTopLevel(const JSPandaFile *jsPandaFile,
446     const CString& requestName, const CString &packagePath)
447 {
448     // we find packagePath/0/xxx or packagePath/1/xxx
449     CString entryPoint;
450     for (size_t level = 0; level <= MAX_PACKAGE_LEVEL; ++level) {
451         CString levelStr = std::to_string(level).c_str();
452         CString key = packagePath + PathHelper::SLASH_TAG + levelStr + PathHelper::SLASH_TAG + requestName;
453         entryPoint = FindNpmEntryPoint(jsPandaFile, key);
454         if (!entryPoint.empty()) {
455             return entryPoint;
456         }
457     }
458     return CString();
459 }
460 
IsImportFile(const CString & moduleRequestName)461 bool ModulePathHelper::IsImportFile(const CString &moduleRequestName)
462 {
463     if (moduleRequestName[0] == PathHelper::POINT_TAG) {
464         return true;
465     }
466     size_t pos = moduleRequestName.rfind(PathHelper::POINT_TAG);
467     if (pos != CString::npos) {
468         CString suffix = moduleRequestName.substr(pos);
469         if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS || suffix == EXT_NAME_JSON) {
470             return true;
471         }
472     }
473     return false;
474 }
475 
476 /*
477  * Before: xxx/xxx.js || xxx/xxx.ts || xxx/xxx.ets ||xxx/xxx.json
478  * After:  xxx/xxx
479  */
RemoveSuffix(const CString & requestName)480 CString ModulePathHelper::RemoveSuffix(const CString &requestName)
481 {
482     CString res = requestName;
483     size_t pos = res.rfind(PathHelper::POINT_TAG);
484     if (pos != CString::npos) {
485         CString suffix = res.substr(pos);
486         if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS || suffix == EXT_NAME_JSON) {
487             res.erase(pos, suffix.length());
488         }
489     }
490     return res;
491 }
492 }  // namespace panda::ecmascript::base