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