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_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 PREFIX_BUNDLE[] = "@bundle:"; 68 static constexpr char PREFIX_MODULE[] = "@module:"; 69 static constexpr char PREFIX_PACKAGE[] = "@package:"; 70 static constexpr char PREFIX_ETS[] = "ets/"; 71 static constexpr char REQUIRE_NAITVE_MODULE_PREFIX[] = "@native:"; 72 static constexpr char REQUIRE_NAPI_OHOS_PREFIX[] = "@ohos:"; 73 static constexpr char REQUIRE_NAPI_APP_PREFIX[] = "@app:"; 74 static constexpr char RAW_ARKUIX_PREFIX[] = "@arkui-x."; 75 static constexpr char NPM_PATH_SEGMENT[] = "node_modules"; 76 static constexpr char PACKAGE_PATH_SEGMENT[] = "pkg_modules"; 77 static constexpr char PACKAGE_ENTRY_FILE[] = "/index"; 78 static constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/"; 79 static constexpr char MERGE_ABC_ETS_MODULES[] = "/ets/modules.abc"; 80 static constexpr char MODULE_DEFAULE_ETS[] = "/ets/"; 81 static constexpr char BUNDLE_SUB_INSTALL_PATH[] = "/data/storage/el1/"; 82 static constexpr char PREVIEW_OF_ACROSS_HAP_FLAG[] = "[preview]"; 83 static constexpr char PREVIER_TEST_DIR[] = ".test"; 84 85 static constexpr size_t MAX_PACKAGE_LEVEL = 1; 86 static constexpr size_t SEGMENTS_LIMIT_TWO = 2; 87 static constexpr size_t EXT_NAME_ABC_LEN = 4; 88 static constexpr size_t EXT_NAME_ETS_LEN = 4; 89 static constexpr size_t EXT_NAME_TS_LEN = 3; 90 static constexpr size_t EXT_NAME_JS_LEN = 3; 91 static constexpr size_t EXT_NAME_JSON_LEN = 5; 92 static constexpr size_t PREFIX_BUNDLE_LEN = 8; 93 static constexpr size_t PREFIX_MODULE_LEN = 8; 94 static constexpr size_t PREFIX_PACKAGE_LEN = 9; 95 static constexpr size_t NATIVE_PREFIX_SIZE = 8; 96 static constexpr size_t OHOS_PREFIX_SIZE = 6; 97 static constexpr size_t APP_PREFIX_SIZE = 5; 98 static constexpr size_t BUNDLE_INSTALL_PATH_LEN = 25; 99 100 static CString ConcatFileNameWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile, 101 CString &baseFileName, CString recordName, CString requestName); 102 static void ParseOhmUrl(EcmaVM *vm, const CString &inputFileName, 103 CString &outBaseFileName, CString &outEntryPoint); 104 static CString ParseUrl(EcmaVM *vm, const CString &recordName); 105 static CString ParsePrefixBundle(JSThread *thread, const JSPandaFile *jsPandaFile, 106 [[maybe_unused]] CString &baseFileName, CString moduleRequestName, [[maybe_unused]] CString recordName); 107 static CString MakeNewRecord(const JSPandaFile *jsPandaFile, CString &baseFileName, 108 const CString &recordName, const CString &requestName); 109 static CString FindOhpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &ohpmPath, 110 const CString &requestName); 111 static CString FindPackageInTopLevelWithNamespace(const JSPandaFile *jsPandaFile, const CString &requestName, 112 const CString &recordName); 113 static CString ParseOhpmPackage(const JSPandaFile *jsPandaFile, const CString &recordName, 114 const CString &requestName); 115 static CString ParseThirdPartyPackage(const JSPandaFile *jsPandaFile, const CString &recordName, 116 const CString &requestName, const CString &packagePath); 117 static CString ParseThirdPartyPackage(const JSPandaFile *jsPandaFile, const CString &recordName, 118 const CString &requestName); 119 static void ResolveCurrentPath(JSThread *thread, JSMutableHandle<JSTaggedValue> &dirPath, 120 JSMutableHandle<JSTaggedValue> &fileName, const JSPandaFile *jsPandaFile); 121 static CString FindNpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint); 122 static CString FindPackageInTopLevel(const JSPandaFile *jsPandaFile, const CString &requestName, 123 const CString &packagePath); 124 static bool IsImportFile(const CString &moduleRequestName); 125 static CString RemoveSuffix(const CString &requestName); 126 static bool NeedTranstale(const CString &requestName); 127 static void TranstaleExpressionInput(JSThread *thread, CString &requestPath, const JSPandaFile *jsPandaFile, 128 JSHandle<EcmaString> &specifierString); 129 static CString GetModuleNameWithBaseFile(const CString &baseFileName); 130 static CString TranslateExpressionInputWithEts(JSThread *thread, const JSPandaFile *jsPandaFile, 131 CString &baseFileName, const CString &requestName); 132 /* 133 * Before: data/storage/el1/bundle/moduleName/ets/modules.abc 134 * After: bundle/moduleName 135 */ ParseHapPath(const CString & baseFileName)136 inline static std::string ParseHapPath(const CString &baseFileName) 137 { 138 CString bundleSubInstallName(BUNDLE_SUB_INSTALL_PATH); 139 size_t startStrLen = bundleSubInstallName.length(); 140 if (baseFileName.length() > startStrLen && baseFileName.compare(0, startStrLen, bundleSubInstallName) == 0) { 141 CString hapPath = baseFileName.substr(startStrLen); 142 size_t pos = hapPath.find(MERGE_ABC_ETS_MODULES); 143 if (pos != CString::npos) { 144 return hapPath.substr(0, pos).c_str(); 145 } 146 } 147 return std::string(); 148 } 149 150 /* 151 * Before: xxx 152 * After: xxx || xxx/index 153 */ ConfirmLoadingIndexOrNot(const JSPandaFile * jsPandaFile,const CString & packageEntryPoint)154 inline static CString ConfirmLoadingIndexOrNot(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint) 155 { 156 CString entryPoint = packageEntryPoint; 157 if (jsPandaFile->HasRecord(entryPoint)) { 158 return entryPoint; 159 } 160 // Possible import directory 161 entryPoint += PACKAGE_ENTRY_FILE; 162 entryPoint = PathHelper::NormalizePath(entryPoint); 163 if (jsPandaFile->HasRecord(entryPoint)) { 164 return entryPoint; 165 } 166 return CString(); 167 } 168 IsNativeModuleRequest(const CString & requestName)169 inline static bool IsNativeModuleRequest(const CString &requestName) 170 { 171 if (requestName[0] != PathHelper::NAME_SPACE_TAG) { 172 return false; 173 } 174 if (StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAPI_OHOS_PREFIX) || 175 StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAPI_APP_PREFIX) || 176 StringHelper::StringStartWith(requestName, ModulePathHelper::REQUIRE_NAITVE_MODULE_PREFIX)) { 177 return true; 178 } 179 return false; 180 } 181 182 /* 183 * Before: bundleName/moduleName/ets/xxx/xxx 184 * After: moduleName 185 */ GetModuleName(const CString recordName)186 inline static CString GetModuleName(const CString recordName) 187 { 188 size_t pos1 = recordName.find(PathHelper::SLASH_TAG); 189 if (pos1 != CString::npos) { 190 pos1++; 191 size_t pos2 = recordName.find(PathHelper::SLASH_TAG, pos1); 192 if (pos2 != CString::npos) { 193 CString moduleName = recordName.substr(pos1, pos2 - pos1); 194 PathHelper::DeleteNamespace(moduleName); 195 return moduleName; 196 } 197 } 198 return CString(); 199 } 200 201 /* 202 * Before: @xxx. 203 * After: @xxx: 204 */ ChangeTag(CString & path)205 inline static bool ChangeTag(CString &path) 206 { 207 if (path[0] == PathHelper::NAME_SPACE_TAG) { 208 size_t pos = path.find(PathHelper::POINT_TAG); 209 if (pos != CString::npos) { 210 path.replace(pos, 1, PathHelper::COLON_TAG); // 1: length 211 return true; 212 } 213 } 214 return false; 215 } 216 }; 217 } // namespace panda::ecmascript 218 #endif // ECMASCRIPT_MODULE_MODULE_PATH_HELPER_H