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 ASSERT(pos != CString::npos); 143 CString moduleName = inputFileName.substr(startStrLen, pos - startStrLen); 144 if (moduleName != vm->GetModuleName()) { 145 outFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES; 146 } 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 entryPoint = vm->GetBundleName() + "/" + vm->GetModuleName() + MODULE_DEFAULE_ETS + inputFileName; 155 } 156 } 157 if (StringHelper::StringEndWith(entryPoint, EXT_NAME_ABC)) { 158 entryPoint.erase(entryPoint.length() - EXT_NAME_ABC_LEN, EXT_NAME_ABC_LEN); 159 } 160 return entryPoint; 161 } 162 CropNamespaceIfAbsent(CString & moduleName)163 static void CropNamespaceIfAbsent(CString &moduleName) 164 { 165 size_t pos = moduleName.find(NAME_SPACE_TAG); 166 if (pos == CString::npos) { 167 return; 168 } 169 moduleName.erase(pos, moduleName.size() - pos); 170 } 171 172 // current ohmUrl format : @bundle:bundlename/modulename@namespace/entry/src/index ParseUrl(EcmaVM * vm,const CString & entryPoint)173 static CString ParseUrl(EcmaVM *vm, const CString &entryPoint) 174 { 175 CVector<CString> vec; 176 StringHelper::SplitString(entryPoint, vec, 0, SEGMENTS_LIMIT_TWO); 177 if (vec.size() < SEGMENTS_LIMIT_TWO) { 178 LOG_ECMA(DEBUG) << "ParseUrl SplitString filed, please check Url" << entryPoint; 179 return CString(); 180 } 181 CString bundleName = vec[0]; 182 CString moduleName = vec[1]; 183 CropNamespaceIfAbsent(moduleName); 184 185 CString baseFileName; 186 if (bundleName != vm->GetBundleName()) { 187 // Cross-application 188 baseFileName = 189 BUNDLE_INSTALL_PATH + bundleName + "/" + moduleName + "/" + moduleName + MERGE_ABC_ETS_MODULES; 190 } else if (moduleName != vm->GetModuleName()) { 191 // Intra-application cross hap 192 baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES; 193 } else { 194 baseFileName = CString(); 195 } 196 return baseFileName; 197 } 198 ParseHapPath(const CString & fileName)199 static std::string ParseHapPath(const CString &fileName) 200 { 201 CString bundleSubInstallName(BUNDLE_SUB_INSTALL_PATH); 202 size_t startStrLen = bundleSubInstallName.length(); 203 if (fileName.length() > startStrLen && fileName.compare(0, startStrLen, bundleSubInstallName) == 0) { 204 CString hapPath = fileName.substr(startStrLen); 205 size_t pos = hapPath.find(MERGE_ABC_ETS_MODULES); 206 if (pos != CString::npos) { 207 return hapPath.substr(0, pos).c_str(); 208 } 209 } 210 return std::string(); 211 } 212 CroppingRecord(CString & recordName)213 static void CroppingRecord(CString &recordName) 214 { 215 size_t pos = recordName.find('/'); 216 if (pos != CString::npos) { 217 pos = recordName.find('/', pos + 1); 218 if (pos != CString::npos) { 219 recordName = recordName.substr(pos + 1); 220 } 221 } 222 } 223 ParsePrefixBundle(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,CString moduleRequestName)224 static CString ParsePrefixBundle(JSThread *thread, const JSPandaFile *jsPandaFile, 225 [[maybe_unused]] CString &baseFileName, CString moduleRequestName) 226 { 227 EcmaVM *vm = thread->GetEcmaVM(); 228 moduleRequestName = moduleRequestName.substr(PREFIX_BUNDLE_LEN); 229 CString entryPoint = moduleRequestName; 230 if (jsPandaFile->IsRecordWithBundleName()) { 231 CVector<CString> vec; 232 StringHelper::SplitString(moduleRequestName, vec, 0, SEGMENTS_LIMIT_TWO); 233 if (vec.size() < SEGMENTS_LIMIT_TWO) { 234 LOG_ECMA(DEBUG) << "SplitString filed, please check moduleRequestName"; 235 return CString(); 236 } 237 CString bundleName = vec[0]; 238 CString moduleName = vec[1]; 239 CropNamespaceIfAbsent(moduleName); 240 241 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) 242 if (bundleName != vm->GetBundleName()) { 243 baseFileName = 244 BUNDLE_INSTALL_PATH + bundleName + '/' + moduleName + '/' + moduleName + MERGE_ABC_ETS_MODULES; 245 } else if (moduleName != vm->GetModuleName()) { 246 baseFileName = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_ETS_MODULES; 247 } else { 248 baseFileName = vm->GetAssetPath(); 249 } 250 #else 251 if (bundleName != vm->GetBundleName() || moduleName != vm->GetModuleName()) { 252 entryPoint = PREVIEW_OF_ACROSS_HAP_FLAG; 253 LOG_NO_TAG(ERROR) << "[ArkRuntime Log] Importing shared package is not supported in the Previewer."; 254 } 255 #endif 256 } else { 257 CroppingRecord(entryPoint); 258 } 259 return entryPoint; 260 } 261 MakeNewRecord(const JSPandaFile * jsPandaFile,CString & baseFileName,const CString & recordName,const CString & requestName)262 static CString MakeNewRecord(const JSPandaFile *jsPandaFile, CString &baseFileName, const CString &recordName, 263 const CString &requestName) 264 { 265 CString entryPoint; 266 CString moduleRequestName = RemoveSuffix(requestName); 267 size_t pos = moduleRequestName.find("./"); 268 if (pos == 0) { 269 moduleRequestName = moduleRequestName.substr(2); // 2 means jump "./" 270 } 271 pos = recordName.rfind('/'); 272 if (pos != CString::npos) { 273 entryPoint = recordName.substr(0, pos + 1) + moduleRequestName; 274 } else { 275 entryPoint = moduleRequestName; 276 } 277 entryPoint = NormalizePath(entryPoint); 278 entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, entryPoint); 279 if (!entryPoint.empty()) { 280 return entryPoint; 281 } 282 // the package name may have a '.js' suffix, try to parseThirdPartyPackage 283 entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName, NPM_PATH_SEGMENT); 284 if (!entryPoint.empty()) { 285 return entryPoint; 286 } 287 // Execute abc locally 288 pos = baseFileName.rfind('/'); 289 if (pos != CString::npos) { 290 baseFileName = baseFileName.substr(0, pos + 1) + moduleRequestName + EXT_NAME_ABC; 291 } else { 292 baseFileName = moduleRequestName + EXT_NAME_ABC; 293 } 294 pos = moduleRequestName.rfind('/'); 295 if (pos != CString::npos) { 296 entryPoint = moduleRequestName.substr(pos + 1); 297 } else { 298 entryPoint = moduleRequestName; 299 } 300 return entryPoint; 301 } 302 ConfirmLoadingIndexOrNot(const JSPandaFile * jsPandaFile,const CString & packageEntryPoint)303 static CString ConfirmLoadingIndexOrNot(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint) 304 { 305 CString entryPoint = packageEntryPoint; 306 if (jsPandaFile->HasRecord(entryPoint)) { 307 return entryPoint; 308 } 309 // Possible import directory 310 entryPoint += PACKAGE_ENTRY_FILE; 311 if (jsPandaFile->HasRecord(entryPoint)) { 312 return entryPoint; 313 } 314 return CString(); 315 } 316 FindNpmEntryPoint(const JSPandaFile * jsPandaFile,const CString & packageEntryPoint)317 static CString FindNpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint) 318 { 319 // if we are currently importing a specific file or directory, we will get the entryPoint here 320 CString entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, packageEntryPoint); 321 if (!entryPoint.empty()) { 322 return entryPoint; 323 } 324 // When you come here, must import a packageName 325 return jsPandaFile->GetEntryPoint(packageEntryPoint); 326 } 327 FindPackageInTopLevel(const JSPandaFile * jsPandaFile,const CString & requestName,const CString & packagePath)328 static CString FindPackageInTopLevel(const JSPandaFile *jsPandaFile, const CString& requestName, 329 const CString &packagePath) 330 { 331 // we find node_modules/0/xxx or node_modules/1/xxx 332 CString entryPoint; 333 for (size_t level = 0; level <= MAX_PACKAGE_LEVEL; ++level) { 334 CString levelStr = std::to_string(level).c_str(); 335 CString key = packagePath + "/" + levelStr + '/' + requestName; 336 entryPoint = FindNpmEntryPoint(jsPandaFile, key); 337 if (!entryPoint.empty()) { 338 return entryPoint; 339 } 340 } 341 return CString(); 342 } 343 FindOhpmEntryPoint(const JSPandaFile * jsPandaFile,const CString & ohpmPath,const CString & requestName)344 static CString FindOhpmEntryPoint(const JSPandaFile *jsPandaFile, const CString& ohpmPath, 345 const CString& requestName) 346 { 347 CVector<CString> vec; 348 StringHelper::SplitString(requestName, vec, 0); 349 size_t maxIndex = vec.size() - 1; 350 CString ohpmKey; 351 size_t index = 0; 352 // first we find the ohpmKey by splicing the requestName 353 while (index <= maxIndex) { 354 CString maybeKey = ohpmPath + "/" + StringHelper::JoinString(vec, 0, index); 355 ohpmKey = jsPandaFile->GetNpmEntries(maybeKey); 356 if (!ohpmKey.empty()) { 357 break; 358 } 359 ++index; 360 } 361 if (ohpmKey.empty()) { 362 return CString(); 363 } 364 // second If the ohpmKey is not empty, we will use it to obtain the real entrypoint 365 CString entryPoint; 366 if (index == maxIndex) { 367 // requestName is a packageName 368 entryPoint = jsPandaFile->GetEntryPoint(ohpmKey); 369 } else { 370 // import a specific file or directory 371 ohpmKey = ohpmKey + "/" + StringHelper::JoinString(vec, index + 1, maxIndex); 372 entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, ohpmKey); 373 } 374 return entryPoint; 375 } 376 FindPackageInTopLevelWithNamespace(const JSPandaFile * jsPandaFile,const CString & requestName,const CString & recordName)377 static CString FindPackageInTopLevelWithNamespace(const JSPandaFile *jsPandaFile, const CString& requestName, 378 const CString &recordName) 379 { 380 // find in current module <PACKAGE_PATH_SEGMENT>@[moduleName|namespace]/<requestName> 381 CString entryPoint; 382 CString ohpmPath; 383 if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) { 384 size_t pos = recordName.find('/'); 385 if (pos == CString::npos) { 386 LOG_ECMA(DEBUG) << "wrong recordname : " << recordName; 387 return CString(); 388 } 389 ohpmPath = recordName.substr(0, pos); 390 entryPoint = FindOhpmEntryPoint(jsPandaFile, recordName.substr(0, pos), requestName); 391 } else { 392 CVector<CString> vec; 393 StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO); 394 if (vec.size() < SEGMENTS_LIMIT_TWO) { 395 LOG_ECMA(DEBUG) << "SplitString filed, please check moduleRequestName"; 396 return CString(); 397 } 398 CString moduleName = vec[1]; 399 // If namespace exists, use namespace as moduleName 400 size_t pos = moduleName.find(NAME_SPACE_TAG); 401 if (pos != CString::npos) { 402 moduleName = moduleName.substr(pos + 1); 403 } 404 ohpmPath = CString(PACKAGE_PATH_SEGMENT) + NAME_SPACE_TAG + moduleName; 405 entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName); 406 } 407 if (!entryPoint.empty()) { 408 return entryPoint; 409 } 410 // find in project directory <packagePath>/<requestName> 411 return FindOhpmEntryPoint(jsPandaFile, PACKAGE_PATH_SEGMENT, requestName); 412 } 413 ParseOhpmPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName)414 static CString ParseOhpmPackage(const JSPandaFile *jsPandaFile, const CString &recordName, 415 const CString &requestName) 416 { 417 CString entryPoint; 418 if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) { 419 //this way is thirdPartyPackage import ThirdPartyPackage 420 auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName); 421 CString packageName = info.npmPackageName; 422 size_t pos = packageName.rfind(PACKAGE_PATH_SEGMENT); 423 if (pos != CString::npos) { 424 packageName.erase(pos, packageName.size() - pos); 425 CString ohpmPath = packageName + PACKAGE_PATH_SEGMENT; 426 entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName); 427 if (!entryPoint.empty()) { 428 return entryPoint; 429 } 430 } 431 } 432 // Import packages under the current module or project directory 433 return FindPackageInTopLevelWithNamespace(jsPandaFile, requestName, recordName); 434 } 435 ParseThirdPartyPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName,const CString & packagePath)436 static CString ParseThirdPartyPackage(const JSPandaFile *jsPandaFile, const CString &recordName, 437 const CString &requestName, const CString &packagePath) 438 { 439 CString entryPoint; 440 if (StringHelper::StringStartWith(recordName, packagePath)) { 441 auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName); 442 CString packageName = info.npmPackageName; 443 size_t pos = 0; 444 while (true) { 445 CString key = packageName + '/' + packagePath + "/" + requestName; 446 entryPoint = FindNpmEntryPoint(jsPandaFile, key); 447 if (!entryPoint.empty()) { 448 return entryPoint; 449 } 450 pos = packageName.rfind(packagePath) - 1; 451 if (pos == CString::npos || pos < 0) { 452 break; 453 } 454 packageName.erase(pos, packageName.size() - pos); 455 } 456 } 457 return FindPackageInTopLevel(jsPandaFile, requestName, packagePath); 458 } 459 ParseThirdPartyPackage(const JSPandaFile * jsPandaFile,const CString & recordName,const CString & requestName)460 static CString ParseThirdPartyPackage(const JSPandaFile *jsPandaFile, const CString &recordName, 461 const CString &requestName) 462 { 463 static CVector<CString> packagePaths = {CString(PACKAGE_PATH_SEGMENT), CString(NPM_PATH_SEGMENT)}; 464 // We need to deal with scenarios like this 'json5/' -> 'json5' 465 CString normalizeRequestName = NormalizePath(requestName); 466 CString entryPoint = ParseOhpmPackage(jsPandaFile, recordName, normalizeRequestName); 467 if (!entryPoint.empty()) { 468 return entryPoint; 469 } 470 // Package compatible with old soft link format 471 for (size_t i = 0; i < packagePaths.size(); ++i) { 472 entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, normalizeRequestName, packagePaths[i]); 473 if (!entryPoint.empty()) { 474 return entryPoint; 475 } 476 } 477 return CString(); 478 } 479 IsImportFile(CString & moduleRequestName)480 static bool IsImportFile(CString &moduleRequestName) 481 { 482 if (moduleRequestName[0] == '.') { 483 return true; 484 } 485 size_t pos = moduleRequestName.rfind('.'); 486 if (pos != CString::npos) { 487 CString suffix = moduleRequestName.substr(pos); 488 if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS || suffix == EXT_NAME_JSON) { 489 return true; 490 } 491 } 492 return false; 493 } 494 RemoveSuffix(const CString & requestName)495 static CString RemoveSuffix(const CString &requestName) 496 { 497 CString res = requestName; 498 size_t pos = res.rfind('.'); 499 if (pos != CString::npos) { 500 CString suffix = res.substr(pos); 501 if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS || suffix == EXT_NAME_JSON) { 502 res.erase(pos, suffix.length()); 503 } 504 } 505 return res; 506 } 507 ConcatFileNameWithMerge(JSThread * thread,const JSPandaFile * jsPandaFile,CString & baseFileName,CString recordName,CString requestName)508 static CString ConcatFileNameWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile, CString &baseFileName, 509 CString recordName, CString requestName) 510 { 511 CString entryPoint; 512 if (StringHelper::StringStartWith(requestName, PREFIX_BUNDLE)) { 513 entryPoint = ParsePrefixBundle(thread, jsPandaFile, baseFileName, requestName); 514 } else if (StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) { 515 entryPoint = requestName.substr(PREFIX_PACKAGE_LEN); 516 } else if (IsImportFile(requestName)) { // load a relative pathName. 517 entryPoint = MakeNewRecord(jsPandaFile, baseFileName, recordName, requestName); 518 } else { 519 entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName); 520 } 521 if (entryPoint.empty()) { 522 LOG_ECMA(ERROR) << "Failed to resolve the requested entryPoint. baseFileName : '" << baseFileName << 523 "'. RecordName : '" << recordName << "'. RequestName : '" << requestName << "'."; 524 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 525 CString msg = "failed to load module'" + requestName + "' which imported by '" + 526 recordName + "'. Please check the target path."; 527 JSTaggedValue error = factory->GetJSError(ErrorType::REFERENCE_ERROR, msg.c_str()).GetTaggedValue(); 528 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, entryPoint); 529 } 530 return entryPoint; 531 } 532 }; 533 } // namespace panda::ecmascript::base 534 #endif // ECMASCRIPT_BASE_PATH_HELPER_H