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