* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/platform/module.h"
namespace panda::ecmascript {
* This function use recordName, requestName to get baseFileName and entryPoint.
* The prefiex of "@bundle", "@package" represents the old path encoding format, while "@normalized" represents the
* unified format.
*/
CString ModulePathHelper::ConcatFileNameWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile,
CString &baseFileName, const CString &recordName, const CString &requestName)
{
if (StringHelper::StringStartWith(requestName, PREFIX_NORMALIZED_NOT_CROSS_HAP_FILE)) {
return requestName.substr(PREFIX_NORMALIZED_LEN);
}
if (StringHelper::StringStartWith(requestName, PREFIX_BUNDLE)) {
return ParsePrefixBundle(thread, jsPandaFile, baseFileName, requestName, recordName);
}
if (StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) {
return requestName.substr(PREFIX_PACKAGE_LEN);
}
if (thread->GetEcmaVM()->IsNormalizedOhmUrlPack()) {
return ConcatMergeFileNameToNormalized(thread, jsPandaFile, baseFileName, recordName, requestName);
}
if (IsImportFile(requestName)) {
return MakeNewRecord(thread, jsPandaFile, baseFileName, recordName, requestName);
}
if (StringHelper::StringStartWith(requestName, PREFIX_ETS)) {
CString entryPoint = TranslateExpressionInputWithEts(thread, jsPandaFile, baseFileName, requestName);
if (entryPoint.empty()) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, entryPoint);
}
return entryPoint;
}
CString entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName);
if (entryPoint.empty()) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, entryPoint);
}
return entryPoint;
}
CString ModulePathHelper::ConcatMergeFileNameToNormalized(JSThread *thread, const JSPandaFile *jsPandaFile,
CString &baseFileName, const CString &recordName, CString requestName)
{
if (StringHelper::StringStartWith(requestName, PathHelper::NORMALIZED_OHMURL_TAG)) {
return requestName;
} else if (IsImportFile(requestName)) {
if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
return MakeNewRecord(thread, jsPandaFile, baseFileName, recordName, requestName);
}
CString inputPath = requestName;
CString entryPoint = ConcatImportFileNormalizedOhmurlWithRecordName(thread, jsPandaFile, baseFileName,
recordName, requestName);
if (entryPoint.empty()) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, inputPath, recordName, requestName);
}
return entryPoint;
} else {
TranslateExpressionToNormalized(thread, jsPandaFile, baseFileName, recordName, requestName);
}
return ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName);
}
* Before: requestName: ../xxx1/xxx2 || ./xxx1
* After: 1.&entryPath&version
* 2.bundleName&entryPath&version
*/
CString ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(JSThread *thread,
const JSPandaFile *jsPandaFile, CString &baseFileName, const CString &recordName, const CString &requestName)
{
CString entryPoint;
CVector<CString> res = SplitNormalizedRecordName(recordName);
CString path = res[NORMALIZED_BUNDLE_NAME_INDEX];
path += PathHelper::NORMALIZED_OHMURL_TAG;
path += res[NORMALIZED_IMPORT_PATH_INDEX];
const CString& version = res[NORMALIZED_VERSION_INDEX];
CString moduleRequestName = requestName;
moduleRequestName = RemoveSuffix(moduleRequestName);
size_t pos = moduleRequestName.find(PathHelper::CURRENT_DIREATORY_TAG);
if (pos == 0) {
moduleRequestName = moduleRequestName.substr(CURRENT_DIREATORY_TAG_LEN);
}
pos = path.rfind(PathHelper::SLASH_TAG);
if (pos != CString::npos) {
entryPoint = path.substr(0, pos + 1) + moduleRequestName;
} else {
entryPoint = moduleRequestName;
}
entryPoint = PathHelper::NormalizePath(entryPoint);
moduleRequestName = ConcatImportFileNormalizedOhmurl(entryPoint, "", version);
if (jsPandaFile->HasRecord(moduleRequestName)) {
return moduleRequestName;
}
entryPoint += PACKAGE_ENTRY_FILE;
entryPoint = PathHelper::NormalizePath(entryPoint);
moduleRequestName = ConcatImportFileNormalizedOhmurl(entryPoint, "", version);
if (jsPandaFile->HasRecord(moduleRequestName)) {
return moduleRequestName;
}
moduleRequestName = requestName;
ConcatOtherNormalizedOhmurl(thread->GetEcmaVM(), jsPandaFile, baseFileName, moduleRequestName);
moduleRequestName = ParseNormalizedOhmUrl(thread, baseFileName, recordName, moduleRequestName);
if (jsPandaFile->HasRecord(moduleRequestName)) {
return moduleRequestName;
}
return {};
}
CString ModulePathHelper::ReformatPath(const CString& requestName)
{
CString normalizeStr;
if (StringHelper::StringStartWith(requestName, PACKAGE_PATH_SEGMENT) ||
StringHelper::StringStartWith(requestName, PREFIX_PACKAGE)) {
auto pos = requestName.rfind(PACKAGE_PATH_SEGMENT);
ASSERT(pos != CString::npos);
normalizeStr = requestName.substr(pos + PACKAGE_PATH_SEGMENT_LEN);
} else if (StringHelper::StringStartWith(requestName, REQUIRE_NAPI_APP_PREFIX)) {
auto pos = requestName.find(PathHelper::SLASH_TAG);
pos = requestName.find(PathHelper::SLASH_TAG, pos + 1);
ASSERT(pos != CString::npos);
normalizeStr = requestName.substr(pos + 1);
} else {
normalizeStr = requestName;
}
return normalizeStr;
}
* Before: inputFileName: 1. /data/storage/el1/bundle/moduleName@namespace/ets/xxx/xxx.abc
2. @bundle:bundleName/moduleName/ets/xxx/xxx.abc
3. moduleName/ets/xxx/xxx.abc
4. .test/xxx/xxx.abc
5. xxx/xxx.abc
* After: outBaseFileName: /data/storage/el1/bundle/moduleName/ets/modules.abc
* outEntryPoint: bundleName/moduleName/ets/xxx/xxx
*/
void ModulePathHelper::ParseAbcPathAndOhmUrl(EcmaVM *vm, const CString &inputFileName,
CString &outBaseFileName, CString &outEntryPoint)
{
size_t pos = CString::npos;
if (inputFileName.length() > BUNDLE_INSTALL_PATH_LEN &&
inputFileName.compare(0, BUNDLE_INSTALL_PATH_LEN, BUNDLE_INSTALL_PATH) == 0) {
pos = BUNDLE_INSTALL_PATH_LEN;
}
if (pos != CString::npos) {
pos = inputFileName.find(PathHelper::SLASH_TAG, BUNDLE_INSTALL_PATH_LEN);
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Invalid Ohm url, please check.";
}
CString moduleName = inputFileName.substr(BUNDLE_INSTALL_PATH_LEN, pos - BUNDLE_INSTALL_PATH_LEN);
PathHelper::DeleteNamespace(moduleName);
outBaseFileName = base::ConcatToCString(BUNDLE_INSTALL_PATH, moduleName, MERGE_ABC_ETS_MODULES);
outEntryPoint = base::ConcatToCString(vm->GetBundleName(), PathHelper::SLASH_TAG,
inputFileName.substr(BUNDLE_INSTALL_PATH_LEN));
} else {
if (StringHelper::StringStartWith(inputFileName, PREFIX_BUNDLE)) {
outEntryPoint = inputFileName.substr(PREFIX_BUNDLE_LEN);
outBaseFileName = ParseUrl(vm, outEntryPoint);
} else {
outEntryPoint = GetOutEntryPoint(vm, inputFileName);
}
}
if (StringHelper::StringEndWith(outEntryPoint, EXT_NAME_ABC)) {
outEntryPoint.erase(outEntryPoint.length() - EXT_NAME_ABC_LEN, EXT_NAME_ABC_LEN);
}
if (vm->IsNormalizedOhmUrlPack()) {
outEntryPoint = TransformToNormalizedOhmUrl(vm, inputFileName, outBaseFileName, outEntryPoint);
}
}
CString ModulePathHelper::ConcatUnifiedOhmUrl(const CString &bundleName, const CString &pkgname,
const CString &entryPath, const CString &path, const CString &version)
{
if (!entryPath.empty()) {
return base::ConcatToCString(bundleName, PathHelper::NORMALIZED_OHMURL_TAG, pkgname, PathHelper::SLASH_TAG,
entryPath, path, PathHelper::NORMALIZED_OHMURL_TAG, version);
}
return base::ConcatToCString(bundleName, PathHelper::NORMALIZED_OHMURL_TAG, pkgname, PHYCICAL_FILE_PATH.data(),
path, PathHelper::NORMALIZED_OHMURL_TAG, version);
}
CString ModulePathHelper::ConcatUnifiedOhmUrl(const CString &bundleName, const CString &normalizedpath,
const CString &version)
{
return base::ConcatToCString(bundleName, PathHelper::NORMALIZED_OHMURL_TAG, normalizedpath,
PathHelper::NORMALIZED_OHMURL_TAG, version);
}
CString ModulePathHelper::ConcatPreviewTestUnifiedOhmUrl(const CString &bundleName, const CString &pkgname,
const CString &path, const CString &version)
{
return base::ConcatToCString(bundleName, PathHelper::NORMALIZED_OHMURL_TAG, pkgname, path,
PathHelper::NORMALIZED_OHMURL_TAG, version);
}
CString ModulePathHelper::ConcatHspFileNameCrossBundle(const CString &bundleName, const CString &moduleName)
{
return base::ConcatToCString(BUNDLE_INSTALL_PATH, bundleName, PathHelper::SLASH_TAG, moduleName,
PathHelper::SLASH_TAG, moduleName, MERGE_ABC_ETS_MODULES);
}
CString ModulePathHelper::ConcatHspFileName(const CString &moduleName)
{
return base::ConcatToCString(BUNDLE_INSTALL_PATH, moduleName, MERGE_ABC_ETS_MODULES);
}
CString ModulePathHelper::ThrowInvalidOhmurlError(EcmaVM *vm, const CString &oldEntryPoint)
{
CString errorMsg = "TransformToNormalizedOhmUrl Invalid Ohmurl: " + oldEntryPoint + ", please check.";
THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(vm->GetJSThread(), ErrorType::SYNTAX_ERROR, errorMsg.c_str(),
oldEntryPoint);
}
CString ModulePathHelper::TransformToNormalizedOhmUrl(EcmaVM *vm, const CString &inputFileName,
const CString &baseFileName, const CString &oldEntryPoint)
{
if (oldEntryPoint == ENTRY_MAIN_FUNCTION ||
StringHelper::StringStartWith(oldEntryPoint, PathHelper::NORMALIZED_OHMURL_TAG)) {
return oldEntryPoint;
}
LOG_ECMA(DEBUG) << "TransformToNormalizedOhmUrl inputFileName: " << inputFileName << " oldEntryPoint: " <<
oldEntryPoint << " baseFileName:" << baseFileName;
size_t pos = oldEntryPoint.find(PathHelper::SLASH_TAG);
if (pos == CString::npos) {
return ThrowInvalidOhmurlError(vm, oldEntryPoint);
}
size_t pathPos = oldEntryPoint.find(PathHelper::SLASH_TAG, pos + 1);
if (pathPos == CString::npos) {
return ThrowInvalidOhmurlError(vm, oldEntryPoint);
}
CString path = oldEntryPoint.substr(pathPos);
CString moduleName = oldEntryPoint.substr(pos + 1, pathPos - pos - 1);
if (moduleName.find(PathHelper::NAME_SPACE_TAG) != CString::npos) {
moduleName = PathHelper::GetHarName(moduleName);
}
CString pkgname = vm->GetPkgName(moduleName);
CString currentModuleName = GetModuleNameWithBaseFile(baseFileName);
if (currentModuleName.empty()) {
currentModuleName = moduleName;
}
#if ENABLE_LATEST_OPTIMIZATION
CVector<CString> data {};
vm->GetPkgContextInfoListElements(currentModuleName, pkgname, data);
#else
CVector<CString> data = GetPkgContextInfoListElements(vm, currentModuleName, pkgname);
#endif
if (data.empty()) {
LOG_ECMA(WARN) << "The PkgContextInfo is empty: " << pkgname << " , currentModuleName:" << currentModuleName;
return oldEntryPoint;
}
const CString &entryPath = data[PKGINFO_ENTRY_PATH_INDEX];
const CString &version = data[PKGINFO_VERSION_INDEX];
const CString &bundleName = data[PKGINFO_BUDNLE_NAME_INDEX];
CString subPath = oldEntryPoint.substr(pathPos + 1);
if (StringHelper::StringStartWith(subPath, PREVIER_TEST_DIR)) {
return ConcatPreviewTestUnifiedOhmUrl(bundleName, pkgname, path, version);
}
if (!entryPath.empty() && StringHelper::StringEndWith(entryPath, PathHelper::SLASH_TAG)) {
size_t endPos = entryPath.rfind(PathHelper::SLASH_TAG);
CString subEntryPath = entryPath.substr(0, endPos);
return ConcatUnifiedOhmUrl(bundleName, pkgname, subEntryPath, path, version);
}
return ConcatUnifiedOhmUrl(bundleName, pkgname, "", path, version);
}
* Before: recordName: bundleName/moduleName@namespace/xxx/xxx.abc
* After: Intra-application cross hap: /data/storage/el1/bundle/bundleName/ets/modules.abc
* Cross-application: /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
*/
CString ModulePathHelper::ParseUrl(EcmaVM *vm, const CString &recordName)
{
CVector<CString> vec;
StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO);
if (vec.size() < SEGMENTS_LIMIT_TWO) {
LOG_ECMA(DEBUG) << "ParseUrl SplitString filed, please check Url" << recordName;
return {};
}
CString bundleName = vec[0];
CString moduleName = vec[1];
PathHelper::DeleteNamespace(moduleName);
CString baseFileName;
if (bundleName != vm->GetBundleName()) {
baseFileName = base::ConcatToCString(BUNDLE_INSTALL_PATH, bundleName, PathHelper::SLASH_TAG, moduleName,
PathHelper::SLASH_TAG, moduleName, MERGE_ABC_ETS_MODULES);
} else {
baseFileName = base::ConcatToCString(BUNDLE_INSTALL_PATH, moduleName, MERGE_ABC_ETS_MODULES);
}
return baseFileName;
}
* Before: moduleRequestName: @bundle:bundleName/moduleName@namespace/ets/xxx
* After: baseFileName: 1./data/storage/el1/bundle/moduleName/ets/modules.abc
* 2./data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
* entryPoint: bundleName/moduleName@namespace/ets/xxx
*/
CString ModulePathHelper::ParsePrefixBundle(JSThread *thread, const JSPandaFile *jsPandaFile,
[[maybe_unused]] CString &baseFileName, CString moduleRequestName, [[maybe_unused]] CString recordName)
{
EcmaVM *vm = thread->GetEcmaVM();
moduleRequestName = moduleRequestName.substr(PREFIX_BUNDLE_LEN);
CString entryPoint = moduleRequestName;
if (jsPandaFile->IsRecordWithBundleName()) {
CVector<CString> vec;
StringHelper::SplitString(moduleRequestName, vec, 0, SEGMENTS_LIMIT_TWO);
if (vec.size() < SEGMENTS_LIMIT_TWO) {
LOG_ECMA(FATAL) << " Exceptional module path : " << moduleRequestName << ", abc path: " <<
baseFileName << ", current file name: " << recordName;
}
CString bundleName = vec[0];
CString moduleName = vec[1];
PathHelper::DeleteNamespace(moduleName);
baseFileName = GetBaseFileName(vm, moduleRequestName, baseFileName, bundleName, moduleName, recordName);
} else {
PathHelper::AdaptOldIsaRecord(entryPoint);
}
return entryPoint;
}
CString ModulePathHelper::ParseNormalizedOhmUrl(JSThread *thread, CString &baseFileName, const CString &recordName,
CString requestName)
{
ASSERT(StringHelper::StringStartWith(requestName, PREFIX_NORMALIZED_NOT_SO));
CVector<CString> res = SplitNormalizedOhmurl(requestName);
if (res.size() != NORMALIZED_OHMURL_ARGS_NUM) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, requestName);
}
const CString& moduleName = res[NORMALIZED_MODULE_NAME_INDEX];
const CString& bundleName = res[NORMALIZED_BUNDLE_NAME_INDEX];
if (!bundleName.empty() && !moduleName.empty()) {
baseFileName = ConcatHspFileNameCrossBundle(bundleName, moduleName);
} else if (!moduleName.empty()) {
baseFileName = ConcatHspFileName(moduleName);
} else if (baseFileName.empty()) {
baseFileName = thread->GetEcmaVM()->GetAssetPath();
}
const CString& importPath = res[NORMALIZED_IMPORT_PATH_INDEX];
const CString& version = res[NORMALIZED_VERSION_INDEX];
return ConcatUnifiedOhmUrl(bundleName, importPath, version);
}
* Before: requestName: ../xxx1/xxx2 || ./b
* recordName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx3 || a
* After: entryPoint: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx1/xxx2 || b
* baseFileName: /data/storage/el1/bundle/moduleName/ets/modules.abc || /home/user/src/a
*/
CString ModulePathHelper::MakeNewRecord(JSThread *thread, const JSPandaFile *jsPandaFile, CString &baseFileName,
const CString &recordName, const CString &requestName)
{
CString entryPoint;
CString moduleRequestName = RemoveSuffix(requestName);
size_t pos = moduleRequestName.find(PathHelper::CURRENT_DIREATORY_TAG);
if (pos == 0) {
moduleRequestName = moduleRequestName.substr(2);
}
pos = recordName.rfind(PathHelper::SLASH_TAG);
if (pos != CString::npos) {
entryPoint = recordName.substr(0, pos + 1) + moduleRequestName;
} else {
entryPoint = moduleRequestName;
}
entryPoint = PathHelper::NormalizePath(entryPoint);
entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, entryPoint);
if (!entryPoint.empty()) {
return entryPoint;
}
entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, requestName);
if (!entryPoint.empty()) {
return entryPoint;
}
if (StringHelper::StringStartWith(baseFileName, BUNDLE_INSTALL_PATH) && !jsPandaFile->IsBundlePack() &&
!jsPandaFile->HasRecord(entryPoint)) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, requestName, recordName, entryPoint);
}
pos = baseFileName.rfind(PathHelper::SLASH_TAG);
if (pos != CString::npos) {
baseFileName = base::ConcatToCString(baseFileName.substr(0, pos + 1), moduleRequestName, EXT_NAME_ABC);
} else {
baseFileName = base::ConcatToCString(moduleRequestName, EXT_NAME_ABC);
}
pos = moduleRequestName.rfind(PathHelper::SLASH_TAG);
if (pos != CString::npos) {
entryPoint = moduleRequestName.substr(pos + 1);
} else {
entryPoint = moduleRequestName;
}
return entryPoint;
}
CString ModulePathHelper::FindOhpmEntryPoint(const JSPandaFile *jsPandaFile,
const CString& ohpmPath, const CString& requestName)
{
CVector<CString> vec;
StringHelper::SplitString(requestName, vec, 0);
if (vec.empty()) {
return {};
}
size_t maxIndex = vec.size() - 1;
CString ohpmKey;
size_t index = 0;
while (index <= maxIndex) {
CString maybeKey = base::ConcatToCString(ohpmPath, PathHelper::SLASH_TAG,
StringHelper::JoinString(vec, 0, index));
if (jsPandaFile->FindOhmUrlInPF(maybeKey, ohpmKey)) {
break;
}
++index;
}
if (ohpmKey.empty()) {
return {};
}
CString entryPoint;
if (index == maxIndex) {
entryPoint = jsPandaFile->GetEntryPoint(ohpmKey);
} else {
ohpmKey = base::ConcatToCString(ohpmKey, PathHelper::SLASH_TAG,
StringHelper::JoinString(vec, index + 1, maxIndex));
entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, ohpmKey);
}
return entryPoint;
}
CString ModulePathHelper::FindPackageInTopLevelWithNamespace(const JSPandaFile *jsPandaFile,
const CString& requestName, const CString &recordName)
{
CString entryPoint;
CString ohpmPath;
if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
size_t pos = recordName.find(PathHelper::SLASH_TAG);
if (pos == CString::npos) {
LOG_ECMA(DEBUG) << "wrong recordname : " << recordName;
return {};
}
ohpmPath = recordName.substr(0, pos);
entryPoint = FindOhpmEntryPoint(jsPandaFile, recordName.substr(0, pos), requestName);
} else {
CVector<CString> vec;
StringHelper::SplitString(recordName, vec, 0, SEGMENTS_LIMIT_TWO);
if (vec.size() < SEGMENTS_LIMIT_TWO) {
LOG_ECMA(DEBUG) << "SplitString filed, please check moduleRequestName";
return {};
}
CString moduleName = vec[1];
size_t pos = moduleName.find(PathHelper::NAME_SPACE_TAG);
if (pos != CString::npos) {
moduleName = moduleName.substr(pos + 1);
}
ohpmPath = base::ConcatToCString(PACKAGE_PATH_SEGMENT, PathHelper::NAME_SPACE_TAG, moduleName);
entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
if ((pos != CString::npos) && entryPoint.empty()) {
moduleName = vec[1].substr(0, pos);
ohpmPath = base::ConcatToCString(PACKAGE_PATH_SEGMENT, PathHelper::NAME_SPACE_TAG, moduleName);
entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
}
}
if (!entryPoint.empty()) {
return entryPoint;
}
return FindOhpmEntryPoint(jsPandaFile, CString(PACKAGE_PATH_SEGMENT), requestName);
}
* Before: requestName: requestPkgName
* recordName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
* After: entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
*/
CString ModulePathHelper::ParseOhpmPackage(const JSPandaFile *jsPandaFile,
const CString &recordName, const CString &requestName)
{
if (StringHelper::StringStartWith(recordName, PACKAGE_PATH_SEGMENT)) {
auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName);
CString packageName = info.npmPackageName;
size_t pos = packageName.rfind(PACKAGE_PATH_SEGMENT);
if (pos != CString::npos) {
packageName.erase(pos, packageName.size() - pos);
CString ohpmPath = base::ConcatToCString(packageName, PACKAGE_PATH_SEGMENT);
CString entryPoint = FindOhpmEntryPoint(jsPandaFile, ohpmPath, requestName);
if (!entryPoint.empty()) {
return entryPoint;
}
}
}
return FindPackageInTopLevelWithNamespace(jsPandaFile, requestName, recordName);
}
* Before: requestName: requestPkgName
* recordName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
* packagePath: pkg_modules || node_modules
* After: entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
*/
CString ModulePathHelper::ParseThirdPartyPackage(const JSPandaFile *jsPandaFile,
const CString &recordName, const CString &requestName, const CString &packagePath)
{
if (StringHelper::StringStartWith(recordName, packagePath)) {
auto info = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(recordName);
CString packageName = info.npmPackageName;
size_t pos = 0;
while (true) {
CString key = base::ConcatToCString(packageName, PathHelper::SLASH_TAG, packagePath,
PathHelper::SLASH_TAG, requestName);
CString entryPoint = FindNpmEntryPoint(jsPandaFile, key);
if (!entryPoint.empty()) {
return entryPoint;
}
size_t index = packageName.rfind(packagePath);
ASSERT(index > 0);
pos = index - 1;
if (pos == CString::npos || pos < 0) {
break;
}
packageName.erase(pos, packageName.size() - pos);
}
}
return FindPackageInTopLevel(jsPandaFile, requestName, packagePath);
}
* Before: requestName: requestPkgName
* recordName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx
* After: entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
*/
CString ModulePathHelper::ParseThirdPartyPackage(const JSPandaFile *jsPandaFile,
const CString &recordName, const CString &requestName)
{
CString normalizeRequestName = PathHelper::NormalizePath(requestName);
CString entryPoint = ParseOhpmPackage(jsPandaFile, recordName, normalizeRequestName);
if (!entryPoint.empty()) {
return entryPoint;
}
static CVector<CString> packagePaths = {CString(PACKAGE_PATH_SEGMENT), CString(NPM_PATH_SEGMENT)};
for (auto& packagePath : packagePaths) {
entryPoint = ParseThirdPartyPackage(jsPandaFile, recordName, normalizeRequestName, packagePath);
if (!entryPoint.empty()) {
return entryPoint;
}
}
return {};
}
* Before: dirPath: Undefined
* fileName: Undefined
* After: dirPath: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/
* fileName: pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/xxx.abc
*/
void ModulePathHelper::ResolveCurrentPath(CString &dirPath, CString &fileName, const JSPandaFile *jsPandaFile)
{
ASSERT(jsPandaFile != nullptr);
fileName = jsPandaFile->GetJSPandaFileDesc();
dirPath = PathHelper::ResolveDirPath(fileName);
}
CString ModulePathHelper::FindNpmEntryPoint(const JSPandaFile *jsPandaFile, const CString &packageEntryPoint)
{
CString entryPoint = ConfirmLoadingIndexOrNot(jsPandaFile, packageEntryPoint);
if (!entryPoint.empty()) {
return entryPoint;
}
return jsPandaFile->GetEntryPoint(packageEntryPoint);
}
* Before: requestName: requestPkgName
* packagePath: pkg_modules || node_modules
* After: entryPoint: pkg_modules/.ohpm/requestPkgName/pkg_modules/requestPkgName/xxx
*/
CString ModulePathHelper::FindPackageInTopLevel(const JSPandaFile *jsPandaFile,
const CString& requestName, const CString &packagePath)
{
for (size_t level = 0; level <= MAX_PACKAGE_LEVEL; ++level) {
CString levelStr(std::to_string(level));
CString key = base::ConcatToCString(packagePath, PathHelper::SLASH_TAG, levelStr,
PathHelper::SLASH_TAG, requestName);
CString entryPoint = FindNpmEntryPoint(jsPandaFile, key);
if (!entryPoint.empty()) {
return entryPoint;
}
}
return {};
}
bool ModulePathHelper::IsImportFile(const CString &moduleRequestName)
{
if (moduleRequestName[0] == PathHelper::POINT_TAG) {
return true;
}
size_t pos = moduleRequestName.rfind(PathHelper::POINT_TAG);
if (pos != CString::npos) {
CString suffix = moduleRequestName.substr(pos);
if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS || suffix == EXT_NAME_JSON) {
return true;
}
}
return false;
}
* Before: xxx/xxx.js || xxx/xxx.ts || xxx/xxx.ets ||xxx/xxx.json
* After: xxx/xxx
*/
CString ModulePathHelper::RemoveSuffix(const CString &requestName)
{
CString res = requestName;
size_t pos = res.rfind(PathHelper::POINT_TAG);
if (pos != CString::npos) {
CString suffix = res.substr(pos);
if (suffix == EXT_NAME_JS || suffix == EXT_NAME_TS || suffix == EXT_NAME_ETS ||
suffix == EXT_NAME_JSON || suffix == EXT_NAME_MJS) {
res.erase(pos, suffix.length());
}
}
return res;
}
bool ModulePathHelper::NeedTranslate(const CString &requestName)
{
if (StringHelper::StringStartWith(requestName, PREFIX_BUNDLE) ||
StringHelper::StringStartWith(requestName, PREFIX_PACKAGE) ||
requestName[0] == PathHelper::POINT_TAG ||
(requestName[0] == PathHelper::NAME_SPACE_TAG &&
requestName.find(PathHelper::COLON_TAG) != CString::npos)) {
return false;
}
return true;
}
void ModulePathHelper::TranslateExpressionInput(const JSPandaFile *jsPandaFile, CString &requestPath)
{
LOG_ECMA(DEBUG) << "Enter Translate OhmUrl for DynamicImport, requestPath: " << requestPath;
if (StringHelper::StringStartWith(requestPath, RAW_ARKUIX_PREFIX)) {
requestPath = StringHelper::Replace(requestPath, RAW_ARKUIX_PREFIX, REQUIRE_NAPI_OHOS_PREFIX);
return;
}
CString outEntryPoint;
if (jsPandaFile->FindOhmUrlInPF(requestPath, outEntryPoint)) {
requestPath = outEntryPoint;
} else {
ParseCrossModuleFile(jsPandaFile, requestPath);
}
ChangeTag(requestPath);
}
* Before: 1. /data/storage/el1/bundle/moduleName/ets/xxx/xxx.abc
* 2. /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
* After: moduleName
*/
CString ModulePathHelper::GetModuleNameWithBaseFile(const CString &baseFileName)
{
size_t pos = CString::npos;
if (baseFileName.length() > BUNDLE_INSTALL_PATH_LEN &&
baseFileName.compare(0, BUNDLE_INSTALL_PATH_LEN, BUNDLE_INSTALL_PATH) == 0) {
pos = BUNDLE_INSTALL_PATH_LEN;
}
CString moduleName;
if (pos != CString::npos) {
pos = baseFileName.find(PathHelper::SLASH_TAG, BUNDLE_INSTALL_PATH_LEN);
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Invalid Ohm url, please check.";
}
moduleName = baseFileName.substr(BUNDLE_INSTALL_PATH_LEN, pos - BUNDLE_INSTALL_PATH_LEN);
if (moduleName.find(PathHelper::POINT_STRING_TAG) != CString::npos) {
size_t pathLength = BUNDLE_INSTALL_PATH_LEN + moduleName.size() + 1;
pos = baseFileName.find(PathHelper::SLASH_TAG, pathLength);
moduleName = baseFileName.substr(pathLength, pos - pathLength);
}
}
return moduleName;
}
* Before: ets/xxx/xxx
* After: bundleName/moduleName/ets/xxx/xxx
*/
CString ModulePathHelper::TranslateExpressionInputWithEts(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &baseFileName, const CString &requestName)
{
EcmaVM *vm = thread->GetEcmaVM();
CString moduleName = GetModuleNameWithBaseFile(baseFileName);
CString entryPoint = base::ConcatToCString(vm->GetBundleName(), PathHelper::SLASH_TAG, moduleName,
PathHelper::SLASH_TAG, requestName);
if (!jsPandaFile->HasRecord(entryPoint)) {
return {};
}
return entryPoint;
}
* input requestPath: moduleName/src/main/xxx/xxx/xxx
* moduleName/xxx/xxx
* moduleName : singleLevelName or twoLevelName
* output requestPath: @bundle.bundleName/moduleName/xxx/xxx/xxx
* @bundle.bundleName/moduleName/xxx/xxx
*/
void ModulePathHelper::ParseCrossModuleFile(const JSPandaFile *jsPandaFile, CString &requestPath)
{
size_t pos = requestPath.find(PathHelper::SLASH_TAG);
if (pos == CString::npos) {
return;
}
CString moduleName = requestPath.substr(0, pos);
CString outEntryPoint;
bool isModuleName = jsPandaFile->FindOhmUrlInPF(moduleName, outEntryPoint);
if (!isModuleName) {
pos = requestPath.find(PathHelper::SLASH_TAG, pos + 1);
if (pos == CString::npos) {
return;
}
moduleName = requestPath.substr(0, pos);
isModuleName = jsPandaFile->FindOhmUrlInPF(moduleName, outEntryPoint);
}
if (isModuleName) {
CString relativePath = requestPath.substr(pos);
size_t index = outEntryPoint.rfind(PathHelper::SLASH_TAG);
if (relativePath.find(PHYCICAL_FILE_PATH.data(), 0) == 0) {
requestPath = base::ConcatToCString(outEntryPoint.substr(0, index), PathHelper::SLASH_TAG,
requestPath.substr(pos + PHYCICAL_FILE_PATH_LEN));
return;
}
requestPath = outEntryPoint.substr(0, index) + requestPath.substr(pos);
}
}
CString ModulePathHelper::ParseFileNameToVMAName(const CString &filename)
{
size_t pos = CString::npos;
if (filename.empty()) {
return VMA_NAME_ARKTS_CODE.data();
}
if (filename.find(EXT_NAME_JS) != CString::npos) {
pos = filename.find(EXT_NAME_Z_SO);
if (pos == CString::npos) {
return VMA_NAME_ARKTS_CODE.data();
}
CString moduleName = filename.substr(0, pos);
pos = moduleName.rfind(PathHelper::POINT_TAG);
if (pos == CString::npos) {
return base::ConcatToCString(VMA_NAME_ARKTS_CODE, PathHelper::COLON_TAG, filename);
}
CString realModuleName = moduleName.substr(pos + 1);
CString realFileName = realModuleName;
std::transform(realFileName.begin(), realFileName.end(), realFileName.begin(), ::tolower);
CString file = base::ConcatToCString(PREFIX_LIB, realFileName, EXT_NAME_Z_SO, PathHelper::SLASH_TAG,
realModuleName, EXT_NAME_JS);
return base::ConcatToCString(VMA_NAME_ARKTS_CODE, PathHelper::COLON_TAG, file);
}
if (filename.find(EXT_NAME_ABC) != CString::npos) {
pos = filename.find(BUNDLE_INSTALL_PATH);
if (pos == CString::npos) {
return base::ConcatToCString(VMA_NAME_ARKTS_CODE, PathHelper::COLON_TAG, filename);
}
CString file = filename.substr(BUNDLE_INSTALL_PATH_LEN);
return base::ConcatToCString(VMA_NAME_ARKTS_CODE, PathHelper::COLON_TAG, file);
}
return VMA_NAME_ARKTS_CODE.data();
}
#if !ENABLE_LATEST_OPTIMIZATION
CVector<CString> ModulePathHelper::GetPkgContextInfoListElements(EcmaVM *vm, const CString &moduleName,
const CString &packageName)
{
CVector<CString> resultList;
if (packageName.empty()) {
return resultList;
}
CMap<CString, CMap<CString, CVector<CString>>> pkgContextList = vm->GetPkgContextInfoList();
if (pkgContextList.find(moduleName) == pkgContextList.end()) {
return resultList;
}
CMap<CString, CVector<CString>> pkgList = pkgContextList[moduleName];
if (pkgList.find(packageName) == pkgList.end()) {
return resultList;
}
resultList = pkgList[packageName];
return resultList;
}
#endif
CString ModulePathHelper::ConcatImportFileNormalizedOhmurl(const CString &recordPath, const CString &requestName,
const CString &version)
{
return base::ConcatToCString(recordPath, requestName, PathHelper::NORMALIZED_OHMURL_TAG, version);
}
CString ModulePathHelper::ConcatNativeSoNormalizedOhmurl(const CString &moduleName, const CString &bundleName,
const CString &pkgName, const CString &version)
{
return base::ConcatToCString(PREFIX_NORMALIZED_SO, PathHelper::NORMALIZED_OHMURL_TAG, moduleName,
PathHelper::NORMALIZED_OHMURL_TAG, bundleName, PathHelper::NORMALIZED_OHMURL_TAG, pkgName,
PathHelper::NORMALIZED_OHMURL_TAG, version);
}
CString ModulePathHelper::ConcatNotSoNormalizedOhmurl(const CString &moduleName, const CString &bundleName,
const CString &pkgName, const CString &entryPath, const CString &version)
{
return base::ConcatToCString(PREFIX_NORMALIZED_NOT_SO, PathHelper::NORMALIZED_OHMURL_TAG, moduleName,
PathHelper::NORMALIZED_OHMURL_TAG, bundleName, PathHelper::NORMALIZED_OHMURL_TAG, pkgName,
PathHelper::SLASH_TAG, entryPath, PathHelper::NORMALIZED_OHMURL_TAG, version);
}
bool ModulePathHelper::NeedTranslateToNormalized(const CString &requestName)
{
if (StringHelper::StringStartWith(requestName, PREFIX_NORMALIZED) ||
(requestName[0] == PathHelper::NAME_SPACE_TAG &&
requestName.find(PathHelper::COLON_TAG) != CString::npos)) {
return false;
}
return true;
}
CString ModulePathHelper::TranslateExpressionToNormalized(JSThread *thread, const JSPandaFile *jsPandaFile,
[[maybe_unused]] CString &baseFileName, const CString &recordName, CString &requestPath)
{
if (!NeedTranslateToNormalized(requestPath)) {
return requestPath;
}
if (StringHelper::StringStartWith(requestPath, RAW_ARKUIX_PREFIX)) {
return StringHelper::Replace(requestPath, RAW_ARKUIX_PREFIX, REQUIRE_NAPI_OHOS_PREFIX);
}
EcmaVM *vm = thread->GetEcmaVM();
CString inputPath = requestPath;
if (IsImportFile(requestPath)) {
CString entryPoint = ConcatImportFileNormalizedOhmurlWithRecordName(thread, jsPandaFile, baseFileName,
recordName, requestPath);
if (entryPoint.empty()) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, inputPath, recordName, requestPath);
}
} else if (StringHelper::StringStartWith(requestPath, PREFIX_ETS)) {
size_t pos = recordName.find(PREFIX_ETS);
if (pos != CString::npos) {
requestPath = ConcatImportFileNormalizedOhmurl(recordName.substr(0, pos), requestPath);
}
if (!jsPandaFile->HasRecord(requestPath)) {
THROW_MODULE_NOT_FOUND_ERROR_WITH_RETURN_VALUE(thread, inputPath, recordName, requestPath);
}
} else {
ConcatOtherNormalizedOhmurl(vm, jsPandaFile, baseFileName, requestPath);
}
return requestPath;
}
* Before: requestPath: 1. @ohos.xxx
* 2. har or har/xxx/xxx
* 3. hsp or hsp/xxx/xxx
* 4. libentry.so
* After: requestPath: 1. @ohos:xxx or @native:xxx.xxx
* 2. @normalized:N&moduleName&bundleName&entryPath&version
* 3. @normalized:N&moduleName&bundleName&entryPath&
* 4. @normalized:Y&&bundleName&entryPath&version
*/
void ModulePathHelper::ConcatOtherNormalizedOhmurl(EcmaVM *vm, const JSPandaFile *jsPandaFile,
[[maybe_unused]] const CString &baseFileName, CString &requestPath)
{
CString currentModuleName = GetModuleNameWithBaseFile(baseFileName);
if (currentModuleName.empty()) {
currentModuleName = vm->GetModuleName();
}
CString pkgName = vm->GetPkgNameWithAlias(requestPath);
#if ENABLE_LATEST_OPTIMIZATION
CVector<CString> data {};
vm->GetPkgContextInfoListElements(currentModuleName, pkgName, data);
#else
CVector<CString> data = GetPkgContextInfoListElements(vm, currentModuleName, pkgName);
#endif
if (!data.empty()) {
CString entryPath;
requestPath = ConcatNormalizedOhmurlWithData(data, pkgName, entryPath);
return;
}
CString result;
size_t filePathPos = requestPath.find(PathHelper::SLASH_TAG);
if (filePathPos != CString::npos) {
result = ConcatOtherNormalizedOhmurlWithFilePath(vm, filePathPos, currentModuleName, requestPath);
if (result.empty()) {
filePathPos = requestPath.find(PathHelper::SLASH_TAG, filePathPos + 1);
if (filePathPos != CString::npos) {
result = ConcatOtherNormalizedOhmurlWithFilePath(vm, filePathPos, currentModuleName, requestPath);
}
}
}
if (result.empty()) {
CString outEntryPoint;
if (jsPandaFile->FindOhmUrlInPF(requestPath, outEntryPoint)) {
requestPath = outEntryPoint;
}
ChangeTag(requestPath);
return;
}
requestPath = result;
}
CString ModulePathHelper::ConcatOtherNormalizedOhmurlWithFilePath(EcmaVM *vm, size_t filePathPos,
const CString &moduleName, const CString &requestPath)
{
CString result;
CString alias = requestPath.substr(0, filePathPos);
CString entryPath = requestPath.substr(filePathPos + 1);
CString pkgName = vm->GetPkgNameWithAlias(alias);
#if ENABLE_LATEST_OPTIMIZATION
CVector<CString> data {};
vm->GetPkgContextInfoListElements(moduleName, pkgName, data);
#else
CVector<CString> data = GetPkgContextInfoListElements(vm, moduleName, pkgName);
#endif
if (!data.empty()) {
result = ConcatNormalizedOhmurlWithData(data, pkgName, entryPath);
}
return result;
}
CString ModulePathHelper::ConcatNormalizedOhmurlWithData(const CVector<CString> &data, const CString &pkgName,
CString &entryPath)
{
const CString &bundleName = data[PKGINFO_BUDNLE_NAME_INDEX];
const CString &moduleName = data[PKGINFO_MODULE_NAME_INDEX];
const CString &version = data[PKGINFO_VERSION_INDEX];
if (entryPath.empty()) {
entryPath = data[PKGINFO_ENTRY_PATH_INDEX];
}
const CString &isSO = data[PKGINFO_IS_SO_INDEX];
if (entryPath.find(PathHelper::CURRENT_DIREATORY_TAG) == 0) {
entryPath = entryPath.substr(CURRENT_DIREATORY_TAG_LEN);
}
if (isSO == TRUE_FLAG) {
return ConcatNativeSoNormalizedOhmurl(moduleName, bundleName, pkgName, version);
} else {
entryPath = RemoveSuffix(entryPath);
return ConcatNotSoNormalizedOhmurl(moduleName, bundleName, pkgName, entryPath, version);
}
}
CString ModulePathHelper::TranslateNapiFileRequestPath(JSThread *thread, const CString &modulePath,
const CString &requestName)
{
if (thread->GetEcmaVM()->IsNormalizedOhmUrlPack()) {
CString moduleName = GetModuleNameWithPath(modulePath);
CString res(1, PathHelper::NORMALIZED_OHMURL_TAG);
base::AppendToBaseString(res, moduleName, PHYCICAL_FILE_PATH.data(),
PathHelper::SLASH_TAG, requestName, PathHelper::NORMALIZED_OHMURL_TAG);
return res;
} else {
return base::ConcatToCString(modulePath, PathHelper::SLASH_TAG, requestName);
}
}
CVector<CString> ModulePathHelper::SplitNormalizedOhmurl(const CString &ohmurl)
{
CVector<CString> res;
size_t start = 0;
size_t pos = ohmurl.find(PathHelper::NORMALIZED_OHMURL_TAG);
while (pos != CString::npos) {
CString element = ohmurl.substr(start, pos - start);
res.emplace_back(element);
start = pos + 1;
pos = ohmurl.find(PathHelper::NORMALIZED_OHMURL_TAG, start);
}
CString tail = ohmurl.substr(start);
res.emplace_back(tail);
return res;
}
CVector<CString> ModulePathHelper::SplitNormalizedRecordName(const CString &recordName)
{
CVector<CString> res(NORMALIZED_OHMURL_ARGS_NUM);
int index = NORMALIZED_OHMURL_ARGS_NUM - 1;
CString temp;
int endIndex = static_cast<int>(recordName.size()) - 1;
for (int i = endIndex; i >= 0; i--) {
char element = recordName[i];
if (element == PathHelper::NORMALIZED_OHMURL_TAG) {
res[index] = temp;
index--;
temp = "";
continue;
}
temp = element + temp;
}
if (!temp.empty()) {
res[index] = temp;
}
return res;
}
* Before: 1. bundleName/moduleName/xxx/xxx
2. bunldeName&moduleName/xxx/xxx&
* After: bundleName
*/
CString ModulePathHelper::GetBundleNameWithRecordName(EcmaVM *vm, const CString &recordName)
{
CString bundleName;
if (vm->IsNormalizedOhmUrlPack()) {
CVector<CString> res = ModulePathHelper::SplitNormalizedRecordName(recordName);
bundleName = res[ModulePathHelper::NORMALIZED_BUNDLE_NAME_INDEX];
if (bundleName.empty()) {
bundleName = vm->GetBundleName();
}
} else {
size_t pos = recordName.find(PathHelper::SLASH_TAG);
bundleName = recordName.substr(0, pos);
}
return bundleName;
}
CString ModulePathHelper::Utf8ConvertToString(JSThread *thread, JSTaggedValue str)
{
return EcmaStringAccessor(str).Utf8ConvertToString(thread);
}
bool ModulePathHelper::IsOhmUrl(const CString &str)
{
if (StringHelper::StringStartWith(str, ModulePathHelper::PREFIX_BUNDLE) ||
StringHelper::StringStartWith(str, ModulePathHelper::PREFIX_PACKAGE) ||
StringHelper::StringStartWith(str, ModulePathHelper::PREFIX_NORMALIZED_NOT_SO)) {
return true;
}
return false;
}
bool ModulePathHelper::CheckAndGetRecordName(JSThread *thread, const CString &ohmUrl, CString &recordName)
{
if (StringHelper::StringStartWith(ohmUrl, PREFIX_BUNDLE)) {
recordName = ohmUrl.substr(PREFIX_BUNDLE_LEN);
return true;
} else if (StringHelper::StringStartWith(ohmUrl, PREFIX_PACKAGE)) {
recordName = ohmUrl.substr(PREFIX_PACKAGE_LEN);
return true;
} else if (StringHelper::StringStartWith(ohmUrl, PREFIX_NORMALIZED_NOT_SO)) {
CString str;
recordName = ModulePathHelper::ParseNormalizedOhmUrl(thread, str, " ", ohmUrl);
return true;
}
LOG_ECMA(ERROR) << "the requested OhmUrl: '" + ohmUrl +
", doesn't match current OhmUrl rule, please check build result.";
return false;
}
* Before: ABC: /data/storage/el1/bundle/xxx/xxx/xxx.abc
* Before: ETS_MODULES: /data/storage/el1/bundle/xxx/ets/modules.abc
*/
bool ModulePathHelper::ValidateAbcPath(const CString &baseFileName, ValidateFilePath checkMode)
{
if (baseFileName.length() > BUNDLE_INSTALL_PATH_LEN &&
baseFileName.compare(0, BUNDLE_INSTALL_PATH_LEN, BUNDLE_INSTALL_PATH) == 0) {
if (checkMode == ValidateFilePath::ETS_MODULES &&
baseFileName.rfind(MERGE_ABC_ETS_MODULES) != CString::npos) {
return true;
}
if (checkMode == ValidateFilePath::ABC &&
baseFileName.rfind(ABC) != CString::npos) {
return true;
}
}
return false;
}
std::pair<std::string, std::string> ModulePathHelper::ResolveOhmUrl(std::string ohmUrl)
{
CString url(ohmUrl);
if (StringHelper::StringStartWith(url, PREFIX_BUNDLE)) {
return ResolveOhmUrlStartWithBundle(ohmUrl);
}
if (StringHelper::StringStartWith(url, PREFIX_NORMALIZED_NOT_SO)) {
return ResolveOhmUrlStartWithNormalized(ohmUrl);
}
LOG_FULL(FATAL) << "Invalid Ohm url, please check. OhmUrl: " << ohmUrl;
return {"", ""};
}
std::pair<std::string, std::string> ModulePathHelper::ResolveOhmUrlStartWithBundle(const std::string &ohmUrl)
{
std::string moduleRequestName(ohmUrl.substr(PREFIX_BUNDLE_LEN));
size_t index = moduleRequestName.find('/');
index = moduleRequestName.find('/', index + 1);
if (index == std::string::npos) {
LOG_FULL(FATAL) << "Invalid Ohm url, please check. OhmUrl: " << ohmUrl;
}
std::string bundleAndModuleName = moduleRequestName.substr(0, index);
std::string filePath = moduleRequestName.substr(index + 1);
return {filePath, bundleAndModuleName};
}
std::pair<std::string, std::string> ModulePathHelper::ResolveOhmUrlStartWithNormalized(const std::string &ohmUrl)
{
CVector<CString> res = SplitNormalizedOhmurl(CString(ohmUrl));
if (res.size() != NORMALIZED_OHMURL_ARGS_NUM) {
LOG_FULL(FATAL) << "Invalid Ohm url, please check. OhmUrl: " << ohmUrl;
}
std::string moduleName(res[NORMALIZED_MODULE_NAME_INDEX]);
std::string bundleName(res[NORMALIZED_BUNDLE_NAME_INDEX]);
std::string path(res[NORMALIZED_IMPORT_PATH_INDEX]);
if (bundleName.empty() || moduleName.empty() || path.empty()) {
LOG_FULL(FATAL) << "Invalid Ohm url, please check. OhmUrl: " << ohmUrl;
}
return {path, bundleName + PathHelper::SLASH_TAG + moduleName};
}
bool ModulePathHelper::CheckExportsWithOhmurl(EcmaVM *vm, const CString &baseFileName, const CString ¤tOhmurl,
const CString &importOhmurl)
{
if (!vm->IsNormalizedOhmUrlPack() ||
StringHelper::StringStartWith(importOhmurl, PathHelper::NORMALIZED_OHMURL_TAG)) {
return true;
}
CString importPkgName = GetPkgNameWithNormalizedOhmurl(importOhmurl);
CString currentPkgName = GetPkgNameWithNormalizedOhmurl(currentOhmurl);
if (importPkgName == currentPkgName) {
return true;
}
CString moduleName = GetModuleNameWithBaseFile(baseFileName);
if (moduleName.empty()) {
moduleName = vm->GetModuleName();
}
return vm->CheckOhExportsWithOhmurl(moduleName, importPkgName, importOhmurl);
}
* Before: @normalized:N&[<module name?>]&[<bundle name>?]&<pkg name + /src/main + path>&[<version>?]
* After: 1. @groupName/packageName
* 2. packageName
*/
CString ModulePathHelper::GetPkgNameWithNormalizedOhmurl(const CString &ohmurl)
{
CString packageName {};
CVector<CString> res = SplitNormalizedRecordName(ohmurl);
const CString &importPath = res[NORMALIZED_IMPORT_PATH_INDEX];
size_t slashPos = importPath.find(PathHelper::SLASH_TAG);
if (slashPos == CString::npos) {
return packageName;
}
if (StringHelper::StringStartWith(importPath, PathHelper::NAME_SPACE_TAG)) {
slashPos = importPath.find(PathHelper::SLASH_TAG, slashPos + 1);
}
if (slashPos != CString::npos) {
packageName = importPath.substr(0, slashPos);
}
return packageName;
}
bool ModulePathHelper::IsCrossBundleHsp(const EcmaVM *vm, const CString &ohmurl)
{
CVector<CString> res = SplitNormalizedRecordName(ohmurl);
const CString& bundleName = res[NORMALIZED_BUNDLE_NAME_INDEX];
if (bundleName != vm->GetBundleName()) {
return true;
}
return false;
}
* Before: /data/storage/el1/bundle/moduleName/ets/modules.abc
* After: moduleName
*
* Before: /data/storage/el1/bundle/bundleName/moduleName/moduleName/ets/modules.abc
* After: bundleName/moduleName
*/
CString ModulePathHelper::GetBundleModuleName(const CString &baseFileName)
{
if (baseFileName.length() <= BUNDLE_INSTALL_PATH_LEN ||
baseFileName.compare(0, BUNDLE_INSTALL_PATH_LEN, BUNDLE_INSTALL_PATH) != 0) {
return baseFileName;
}
size_t pos = baseFileName.find(MERGE_ABC_ETS_MODULES);
if (pos == CString::npos) {
return baseFileName;
}
CString moduleName = baseFileName.substr(BUNDLE_INSTALL_PATH_LEN, pos - BUNDLE_INSTALL_PATH_LEN);
size_t slashPos = moduleName.find(PathHelper::SLASH_TAG);
if (slashPos == CString::npos) {
return moduleName;
}
size_t lastSlash = moduleName.rfind(PathHelper::SLASH_TAG);
return moduleName.substr(0, lastSlash);
}
}