13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ciimport { 173af6ab5fSopenharmony_ci factory, 183af6ab5fSopenharmony_ci isStringLiteral, 193af6ab5fSopenharmony_ci isExportDeclaration, 203af6ab5fSopenharmony_ci isImportDeclaration, 213af6ab5fSopenharmony_ci isSourceFile, 223af6ab5fSopenharmony_ci setParentRecursive, 233af6ab5fSopenharmony_ci visitEachChild, 243af6ab5fSopenharmony_ci isStructDeclaration, 253af6ab5fSopenharmony_ci SyntaxKind, 263af6ab5fSopenharmony_ci isConstructorDeclaration, 273af6ab5fSopenharmony_ci} from 'typescript'; 283af6ab5fSopenharmony_ci 293af6ab5fSopenharmony_ciimport type { 303af6ab5fSopenharmony_ci CallExpression, 313af6ab5fSopenharmony_ci Expression, 323af6ab5fSopenharmony_ci ImportDeclaration, 333af6ab5fSopenharmony_ci ExportDeclaration, 343af6ab5fSopenharmony_ci Node, 353af6ab5fSopenharmony_ci StringLiteral, 363af6ab5fSopenharmony_ci TransformationContext, 373af6ab5fSopenharmony_ci Transformer, 383af6ab5fSopenharmony_ci StructDeclaration, 393af6ab5fSopenharmony_ci SourceFile, 403af6ab5fSopenharmony_ci ClassElement, 413af6ab5fSopenharmony_ci ImportCall, 423af6ab5fSopenharmony_ci TransformerFactory, 433af6ab5fSopenharmony_ci} from 'typescript'; 443af6ab5fSopenharmony_ci 453af6ab5fSopenharmony_ciimport fs from 'fs'; 463af6ab5fSopenharmony_ciimport path from 'path'; 473af6ab5fSopenharmony_ci 483af6ab5fSopenharmony_ciimport type { IOptions } from '../../configs/IOptions'; 493af6ab5fSopenharmony_ciimport type { TransformPlugin } from '../TransformPlugin'; 503af6ab5fSopenharmony_ciimport { TransformerOrder } from '../TransformPlugin'; 513af6ab5fSopenharmony_ciimport type { IFileNameObfuscationOption } from '../../configs/INameObfuscationOption'; 523af6ab5fSopenharmony_ciimport { OhmUrlStatus } from '../../configs/INameObfuscationOption'; 533af6ab5fSopenharmony_ciimport { NameGeneratorType, getNameGenerator } from '../../generator/NameFactory'; 543af6ab5fSopenharmony_ciimport type { INameGenerator, NameGeneratorOptions } from '../../generator/INameGenerator'; 553af6ab5fSopenharmony_ciimport { FileUtils, BUNDLE, NORMALIZE } from '../../utils/FileUtils'; 563af6ab5fSopenharmony_ciimport { NodeUtils } from '../../utils/NodeUtils'; 573af6ab5fSopenharmony_ciimport { orignalFilePathForSearching, performancePrinter, ArkObfuscator } from '../../ArkObfuscator'; 583af6ab5fSopenharmony_ciimport type { PathAndExtension, ProjectInfo } from '../../common/type'; 593af6ab5fSopenharmony_ciimport { EventList } from '../../utils/PrinterUtils'; 603af6ab5fSopenharmony_ciimport { needToBeReserved } from '../../utils/TransformUtil'; 613af6ab5fSopenharmony_cinamespace secharmony { 623af6ab5fSopenharmony_ci 633af6ab5fSopenharmony_ci // global mangled file name table used by all files in a project 643af6ab5fSopenharmony_ci export let globalFileNameMangledTable: Map<string, string> = new Map<string, string>(); 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ci // used for file name cache 673af6ab5fSopenharmony_ci export let historyFileNameMangledTable: Map<string, string> = undefined; 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_ci // When the module is compiled, call this function to clear global collections related to file name. 703af6ab5fSopenharmony_ci export function clearCaches(): void { 713af6ab5fSopenharmony_ci globalFileNameMangledTable.clear(); 723af6ab5fSopenharmony_ci historyFileNameMangledTable?.clear(); 733af6ab5fSopenharmony_ci } 743af6ab5fSopenharmony_ci 753af6ab5fSopenharmony_ci let profile: IFileNameObfuscationOption | undefined; 763af6ab5fSopenharmony_ci let generator: INameGenerator | undefined; 773af6ab5fSopenharmony_ci let reservedFileNames: Set<string> | undefined; 783af6ab5fSopenharmony_ci let localPackageSet: Set<string> | undefined; 793af6ab5fSopenharmony_ci let useNormalized: boolean = false; 803af6ab5fSopenharmony_ci let universalReservedFileNames: RegExp[] | undefined; 813af6ab5fSopenharmony_ci 823af6ab5fSopenharmony_ci /** 833af6ab5fSopenharmony_ci * Rename Properties Transformer 843af6ab5fSopenharmony_ci * 853af6ab5fSopenharmony_ci * @param option obfuscation options 863af6ab5fSopenharmony_ci */ 873af6ab5fSopenharmony_ci const createRenameFileNameFactory = function (options: IOptions): TransformerFactory<Node> { 883af6ab5fSopenharmony_ci profile = options?.mRenameFileName; 893af6ab5fSopenharmony_ci if (!profile || !profile.mEnable) { 903af6ab5fSopenharmony_ci return null; 913af6ab5fSopenharmony_ci } 923af6ab5fSopenharmony_ci 933af6ab5fSopenharmony_ci let nameGeneratorOption: NameGeneratorOptions = {}; 943af6ab5fSopenharmony_ci 953af6ab5fSopenharmony_ci generator = getNameGenerator(profile.mNameGeneratorType, nameGeneratorOption); 963af6ab5fSopenharmony_ci let configReservedFileNameOrPath: string[] = profile?.mReservedFileNames ?? []; 973af6ab5fSopenharmony_ci const tempReservedName: string[] = ['.', '..', '']; 983af6ab5fSopenharmony_ci configReservedFileNameOrPath.map(fileNameOrPath => { 993af6ab5fSopenharmony_ci if (!fileNameOrPath || fileNameOrPath.length === 0) { 1003af6ab5fSopenharmony_ci return; 1013af6ab5fSopenharmony_ci } 1023af6ab5fSopenharmony_ci const directories = FileUtils.splitFilePath(fileNameOrPath); 1033af6ab5fSopenharmony_ci directories.forEach(directory => { 1043af6ab5fSopenharmony_ci tempReservedName.push(directory); 1053af6ab5fSopenharmony_ci const pathOrExtension: PathAndExtension = FileUtils.getFileSuffix(directory); 1063af6ab5fSopenharmony_ci if (pathOrExtension.ext) { 1073af6ab5fSopenharmony_ci tempReservedName.push(pathOrExtension.ext); 1083af6ab5fSopenharmony_ci tempReservedName.push(pathOrExtension.path); 1093af6ab5fSopenharmony_ci } 1103af6ab5fSopenharmony_ci }); 1113af6ab5fSopenharmony_ci }); 1123af6ab5fSopenharmony_ci reservedFileNames = new Set<string>(tempReservedName); 1133af6ab5fSopenharmony_ci universalReservedFileNames = profile?.mUniversalReservedFileNames ?? []; 1143af6ab5fSopenharmony_ci return renameFileNameFactory; 1153af6ab5fSopenharmony_ci 1163af6ab5fSopenharmony_ci function renameFileNameFactory(context: TransformationContext): Transformer<Node> { 1173af6ab5fSopenharmony_ci let projectInfo: ProjectInfo = ArkObfuscator.mProjectInfo; 1183af6ab5fSopenharmony_ci if (projectInfo && projectInfo.localPackageSet) { 1193af6ab5fSopenharmony_ci localPackageSet = projectInfo.localPackageSet; 1203af6ab5fSopenharmony_ci useNormalized = projectInfo.useNormalized; 1213af6ab5fSopenharmony_ci } 1223af6ab5fSopenharmony_ci 1233af6ab5fSopenharmony_ci return renameFileNameTransformer; 1243af6ab5fSopenharmony_ci 1253af6ab5fSopenharmony_ci function renameFileNameTransformer(node: Node): Node { 1263af6ab5fSopenharmony_ci if (globalFileNameMangledTable === undefined) { 1273af6ab5fSopenharmony_ci globalFileNameMangledTable = new Map<string, string>(); 1283af6ab5fSopenharmony_ci } 1293af6ab5fSopenharmony_ci 1303af6ab5fSopenharmony_ci performancePrinter?.singleFilePrinter?.startEvent(EventList.FILENAME_OBFUSCATION, performancePrinter.timeSumPrinter); 1313af6ab5fSopenharmony_ci let ret: Node = updateNodeInfo(node); 1323af6ab5fSopenharmony_ci if (!isInOhModules(projectInfo, orignalFilePathForSearching) && isSourceFile(ret)) { 1333af6ab5fSopenharmony_ci const orignalAbsPath = ret.fileName; 1343af6ab5fSopenharmony_ci const mangledAbsPath: string = getMangleCompletePath(orignalAbsPath); 1353af6ab5fSopenharmony_ci ret.fileName = mangledAbsPath; 1363af6ab5fSopenharmony_ci } 1373af6ab5fSopenharmony_ci let parentNodes = setParentRecursive(ret, true); 1383af6ab5fSopenharmony_ci performancePrinter?.singleFilePrinter?.endEvent(EventList.FILENAME_OBFUSCATION, performancePrinter.timeSumPrinter); 1393af6ab5fSopenharmony_ci return parentNodes; 1403af6ab5fSopenharmony_ci } 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_ci function updateNodeInfo(node: Node): Node { 1433af6ab5fSopenharmony_ci if (isImportDeclaration(node) || isExportDeclaration(node)) { 1443af6ab5fSopenharmony_ci return updateImportOrExportDeclaration(node); 1453af6ab5fSopenharmony_ci } 1463af6ab5fSopenharmony_ci 1473af6ab5fSopenharmony_ci if (isImportCall(node)) { 1483af6ab5fSopenharmony_ci return tryUpdateDynamicImport(node); 1493af6ab5fSopenharmony_ci } 1503af6ab5fSopenharmony_ci 1513af6ab5fSopenharmony_ci return visitEachChild(node, updateNodeInfo, context); 1523af6ab5fSopenharmony_ci } 1533af6ab5fSopenharmony_ci } 1543af6ab5fSopenharmony_ci }; 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ci export function isInOhModules(proInfo: ProjectInfo, originalPath: string): boolean { 1573af6ab5fSopenharmony_ci let ohPackagePath: string = ''; 1583af6ab5fSopenharmony_ci if (proInfo && proInfo.projectRootPath && proInfo.packageDir) { 1593af6ab5fSopenharmony_ci ohPackagePath = FileUtils.toUnixPath(path.resolve(proInfo.projectRootPath, proInfo.packageDir)); 1603af6ab5fSopenharmony_ci } 1613af6ab5fSopenharmony_ci return ohPackagePath && FileUtils.toUnixPath(originalPath).indexOf(ohPackagePath) !== -1; 1623af6ab5fSopenharmony_ci } 1633af6ab5fSopenharmony_ci 1643af6ab5fSopenharmony_ci function updateImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration): ImportDeclaration | ExportDeclaration { 1653af6ab5fSopenharmony_ci if (!node.moduleSpecifier) { 1663af6ab5fSopenharmony_ci return node; 1673af6ab5fSopenharmony_ci } 1683af6ab5fSopenharmony_ci const mangledModuleSpecifier = renameStringLiteral(node.moduleSpecifier as StringLiteral); 1693af6ab5fSopenharmony_ci if (isImportDeclaration(node)) { 1703af6ab5fSopenharmony_ci return factory.updateImportDeclaration(node, node.modifiers, node.importClause, mangledModuleSpecifier as Expression, node.assertClause); 1713af6ab5fSopenharmony_ci } else { 1723af6ab5fSopenharmony_ci return factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, mangledModuleSpecifier as Expression, 1733af6ab5fSopenharmony_ci node.assertClause); 1743af6ab5fSopenharmony_ci } 1753af6ab5fSopenharmony_ci } 1763af6ab5fSopenharmony_ci 1773af6ab5fSopenharmony_ci export function updateImportOrExportDeclarationForTest(node: ImportDeclaration | ExportDeclaration): ImportDeclaration | ExportDeclaration { 1783af6ab5fSopenharmony_ci return updateImportOrExportDeclaration(node); 1793af6ab5fSopenharmony_ci } 1803af6ab5fSopenharmony_ci 1813af6ab5fSopenharmony_ci function isImportCall(n: Node): n is ImportCall { 1823af6ab5fSopenharmony_ci return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.ImportKeyword; 1833af6ab5fSopenharmony_ci } 1843af6ab5fSopenharmony_ci 1853af6ab5fSopenharmony_ci function canBeObfuscatedFilePath(filePath: string): boolean { 1863af6ab5fSopenharmony_ci return path.isAbsolute(filePath) || FileUtils.isRelativePath(filePath) || isLocalDependencyOhmUrl(filePath); 1873af6ab5fSopenharmony_ci } 1883af6ab5fSopenharmony_ci 1893af6ab5fSopenharmony_ci function isLocalDependencyOhmUrl(filePath: string): boolean { 1903af6ab5fSopenharmony_ci // mOhmUrlStatus: for unit test in Arkguard 1913af6ab5fSopenharmony_ci if (profile?.mOhmUrlStatus === OhmUrlStatus.AT_BUNDLE || 1923af6ab5fSopenharmony_ci profile?.mOhmUrlStatus === OhmUrlStatus.NORMALIZED) { 1933af6ab5fSopenharmony_ci return true; 1943af6ab5fSopenharmony_ci } 1953af6ab5fSopenharmony_ci 1963af6ab5fSopenharmony_ci let packageName: string; 1973af6ab5fSopenharmony_ci // Only hap and local har need be mangled. 1983af6ab5fSopenharmony_ci if (useNormalized) { 1993af6ab5fSopenharmony_ci if (!filePath.startsWith(NORMALIZE)) { 2003af6ab5fSopenharmony_ci return false; 2013af6ab5fSopenharmony_ci } 2023af6ab5fSopenharmony_ci packageName = handleNormalizedOhmUrl(filePath, true); 2033af6ab5fSopenharmony_ci } else { 2043af6ab5fSopenharmony_ci if (!filePath.startsWith(BUNDLE)) { 2053af6ab5fSopenharmony_ci return false; 2063af6ab5fSopenharmony_ci } 2073af6ab5fSopenharmony_ci packageName = getAtBundlePgkName(filePath); 2083af6ab5fSopenharmony_ci } 2093af6ab5fSopenharmony_ci return localPackageSet && localPackageSet.has(packageName); 2103af6ab5fSopenharmony_ci } 2113af6ab5fSopenharmony_ci 2123af6ab5fSopenharmony_ci export function isLocalDependencyOhmUrlForTest(filePath: string): boolean { 2133af6ab5fSopenharmony_ci return isLocalDependencyOhmUrl(filePath); 2143af6ab5fSopenharmony_ci } 2153af6ab5fSopenharmony_ci 2163af6ab5fSopenharmony_ci function getAtBundlePgkName(ohmUrl: string): string { 2173af6ab5fSopenharmony_ci /* Unnormalized OhmUrl Format: 2183af6ab5fSopenharmony_ci * hap/hsp: @bundle:${bundleName}/${moduleName}/ 2193af6ab5fSopenharmony_ci * har: @bundle:${bundleName}/${moduleName}@${harName}/ 2203af6ab5fSopenharmony_ci * package name is {moduleName} in hap/hsp or {harName} in har. 2213af6ab5fSopenharmony_ci */ 2223af6ab5fSopenharmony_ci let moduleName: string = ohmUrl.split('/')[1]; // 1: the index of moduleName in array. 2233af6ab5fSopenharmony_ci const indexOfSign: number = moduleName.indexOf('@'); 2243af6ab5fSopenharmony_ci if (indexOfSign !== -1) { 2253af6ab5fSopenharmony_ci moduleName = moduleName.slice(indexOfSign + 1); // 1: the index start from indexOfSign + 1. 2263af6ab5fSopenharmony_ci } 2273af6ab5fSopenharmony_ci return moduleName; 2283af6ab5fSopenharmony_ci } 2293af6ab5fSopenharmony_ci 2303af6ab5fSopenharmony_ci // dynamic import example: let module = import('./a') 2313af6ab5fSopenharmony_ci function tryUpdateDynamicImport(node: CallExpression): CallExpression { 2323af6ab5fSopenharmony_ci if (node.expression && node.arguments.length === 1 && isStringLiteral(node.arguments[0])) { 2333af6ab5fSopenharmony_ci const obfuscatedArgument = [renameStringLiteral(node.arguments[0] as StringLiteral)]; 2343af6ab5fSopenharmony_ci if (obfuscatedArgument[0] !== node.arguments[0]) { 2353af6ab5fSopenharmony_ci return factory.updateCallExpression(node, node.expression, node.typeArguments, obfuscatedArgument); 2363af6ab5fSopenharmony_ci } 2373af6ab5fSopenharmony_ci } 2383af6ab5fSopenharmony_ci return node; 2393af6ab5fSopenharmony_ci } 2403af6ab5fSopenharmony_ci 2413af6ab5fSopenharmony_ci function renameStringLiteral(node: StringLiteral): Expression { 2423af6ab5fSopenharmony_ci let expr: StringLiteral = renameFileName(node) as StringLiteral; 2433af6ab5fSopenharmony_ci if (expr !== node) { 2443af6ab5fSopenharmony_ci return factory.createStringLiteral(expr.text); 2453af6ab5fSopenharmony_ci } 2463af6ab5fSopenharmony_ci return node; 2473af6ab5fSopenharmony_ci } 2483af6ab5fSopenharmony_ci 2493af6ab5fSopenharmony_ci function renameFileName(node: StringLiteral): Node { 2503af6ab5fSopenharmony_ci let original: string = ''; 2513af6ab5fSopenharmony_ci original = node.text; 2523af6ab5fSopenharmony_ci original = original.replace(/\\/g, '/'); 2533af6ab5fSopenharmony_ci 2543af6ab5fSopenharmony_ci if (!canBeObfuscatedFilePath(original)) { 2553af6ab5fSopenharmony_ci return node; 2563af6ab5fSopenharmony_ci } 2573af6ab5fSopenharmony_ci 2583af6ab5fSopenharmony_ci let mangledFileName: string = getMangleIncompletePath(original); 2593af6ab5fSopenharmony_ci if (mangledFileName === original) { 2603af6ab5fSopenharmony_ci return node; 2613af6ab5fSopenharmony_ci } 2623af6ab5fSopenharmony_ci 2633af6ab5fSopenharmony_ci return factory.createStringLiteral(mangledFileName); 2643af6ab5fSopenharmony_ci } 2653af6ab5fSopenharmony_ci 2663af6ab5fSopenharmony_ci export function getMangleCompletePath(originalCompletePath: string): string { 2673af6ab5fSopenharmony_ci originalCompletePath = FileUtils.toUnixPath(originalCompletePath); 2683af6ab5fSopenharmony_ci const { path: filePathWithoutSuffix, ext: extension } = FileUtils.getFileSuffix(originalCompletePath); 2693af6ab5fSopenharmony_ci const mangleFilePath = mangleFileName(filePathWithoutSuffix); 2703af6ab5fSopenharmony_ci return mangleFilePath + extension; 2713af6ab5fSopenharmony_ci } 2723af6ab5fSopenharmony_ci 2733af6ab5fSopenharmony_ci function getMangleIncompletePath(orignalPath: string): string { 2743af6ab5fSopenharmony_ci // The ohmUrl format does not have file extension 2753af6ab5fSopenharmony_ci if (isLocalDependencyOhmUrl(orignalPath)) { 2763af6ab5fSopenharmony_ci const mangledOhmUrl = mangleOhmUrl(orignalPath); 2773af6ab5fSopenharmony_ci return mangledOhmUrl; 2783af6ab5fSopenharmony_ci } 2793af6ab5fSopenharmony_ci 2803af6ab5fSopenharmony_ci // Try to concat the extension for orignalPath. 2813af6ab5fSopenharmony_ci const pathAndExtension : PathAndExtension | undefined = tryValidateFileExisting(orignalPath); 2823af6ab5fSopenharmony_ci if (!pathAndExtension) { 2833af6ab5fSopenharmony_ci return orignalPath; 2843af6ab5fSopenharmony_ci } 2853af6ab5fSopenharmony_ci 2863af6ab5fSopenharmony_ci if (pathAndExtension.ext) { 2873af6ab5fSopenharmony_ci const mangleFilePath = mangleFileName(pathAndExtension.path); 2883af6ab5fSopenharmony_ci return mangleFilePath; 2893af6ab5fSopenharmony_ci } 2903af6ab5fSopenharmony_ci /** 2913af6ab5fSopenharmony_ci * import * from './filename1.js'. We just need to obfuscate 'filename1' and then concat the extension 'js'. 2923af6ab5fSopenharmony_ci * import * from './direcotry'. For the grammar of importing directory, TSC will look for index.ets/index.ts when parsing. 2933af6ab5fSopenharmony_ci * We obfuscate directory name and do not need to concat extension. 2943af6ab5fSopenharmony_ci */ 2953af6ab5fSopenharmony_ci const { path: filePathWithoutSuffix, ext: extension } = FileUtils.getFileSuffix(pathAndExtension.path); 2963af6ab5fSopenharmony_ci const mangleFilePath = mangleFileName(filePathWithoutSuffix); 2973af6ab5fSopenharmony_ci return mangleFilePath + extension; 2983af6ab5fSopenharmony_ci } 2993af6ab5fSopenharmony_ci 3003af6ab5fSopenharmony_ci export function getMangleIncompletePathForTest(orignalPath: string): string { 3013af6ab5fSopenharmony_ci return getMangleIncompletePath(orignalPath); 3023af6ab5fSopenharmony_ci }; 3033af6ab5fSopenharmony_ci 3043af6ab5fSopenharmony_ci export function mangleOhmUrl(ohmUrl: string): string { 3053af6ab5fSopenharmony_ci let mangledOhmUrl: string; 3063af6ab5fSopenharmony_ci // mOhmUrlStatus: for unit test in Arkguard 3073af6ab5fSopenharmony_ci if (useNormalized || profile?.mOhmUrlStatus === OhmUrlStatus.NORMALIZED) { 3083af6ab5fSopenharmony_ci mangledOhmUrl = handleNormalizedOhmUrl(ohmUrl); 3093af6ab5fSopenharmony_ci } else { 3103af6ab5fSopenharmony_ci /** 3113af6ab5fSopenharmony_ci * OhmUrl Format: 3123af6ab5fSopenharmony_ci * fixed parts in hap/hsp: @bundle:${bundleName}/${moduleName}/ 3133af6ab5fSopenharmony_ci * fixed parts in har: @bundle:${bundleName}/${moduleName}@${harName}/ 3143af6ab5fSopenharmony_ci * hsp example: @bundle:com.example.myapplication/entry/index 3153af6ab5fSopenharmony_ci * har example: @bundle:com.example.myapplication/entry@library_test/index 3163af6ab5fSopenharmony_ci * we do not mangle fixed parts. 3173af6ab5fSopenharmony_ci */ 3183af6ab5fSopenharmony_ci const originalOhmUrlSegments: string[] = FileUtils.splitFilePath(ohmUrl); 3193af6ab5fSopenharmony_ci const prefixSegments: string[] = originalOhmUrlSegments.slice(0, 2); // 2: length of fixed parts in array 3203af6ab5fSopenharmony_ci const urlSegments: string[] = originalOhmUrlSegments.slice(2); // 2: index of mangled parts in array 3213af6ab5fSopenharmony_ci const mangledOhmUrlSegments: string[] = urlSegments.map(originalSegment => mangleFileNamePart(originalSegment)); 3223af6ab5fSopenharmony_ci mangledOhmUrl = prefixSegments.join('/') + '/' + mangledOhmUrlSegments.join('/'); 3233af6ab5fSopenharmony_ci } 3243af6ab5fSopenharmony_ci return mangledOhmUrl; 3253af6ab5fSopenharmony_ci } 3263af6ab5fSopenharmony_ci 3273af6ab5fSopenharmony_ci /** 3283af6ab5fSopenharmony_ci * Normalized OhmUrl Format: 3293af6ab5fSopenharmony_ci * hap/hsp: @normalized:N&<module name>&<bundle name>&<standard import path>& 3303af6ab5fSopenharmony_ci * har: @normalized:N&&<bundle name>&<standard import path>&<version> 3313af6ab5fSopenharmony_ci * we only mangle <standard import path>. 3323af6ab5fSopenharmony_ci */ 3333af6ab5fSopenharmony_ci export function handleNormalizedOhmUrl(ohmUrl: string, needPkgName?: boolean): string { 3343af6ab5fSopenharmony_ci let originalOhmUrlSegments: string[] = ohmUrl.split('&'); 3353af6ab5fSopenharmony_ci const standardImportPath = originalOhmUrlSegments[3]; // 3: index of standard import path in array. 3363af6ab5fSopenharmony_ci let index = standardImportPath.indexOf('/'); 3373af6ab5fSopenharmony_ci // The format of <module name>: @group/packagename or packagename, 3383af6ab5fSopenharmony_ci // and there should only be one '@' symbol and one path separator '/' if and only if the 'group' exists. 3393af6ab5fSopenharmony_ci if (standardImportPath.startsWith('@')) { 3403af6ab5fSopenharmony_ci index = standardImportPath.indexOf('/', index + 1); 3413af6ab5fSopenharmony_ci } 3423af6ab5fSopenharmony_ci 3433af6ab5fSopenharmony_ci const pakName = standardImportPath.substring(0, index); 3443af6ab5fSopenharmony_ci if (needPkgName) { 3453af6ab5fSopenharmony_ci return pakName; 3463af6ab5fSopenharmony_ci } 3473af6ab5fSopenharmony_ci const realImportPath = standardImportPath.substring(index + 1); // 1: index of real import path in array. 3483af6ab5fSopenharmony_ci const originalImportPathSegments: string[] = FileUtils.splitFilePath(realImportPath); 3493af6ab5fSopenharmony_ci const mangledImportPathSegments: string[] = originalImportPathSegments.map(originalSegment => mangleFileNamePart(originalSegment)); 3503af6ab5fSopenharmony_ci const mangledImportPath: string = pakName + '/' + mangledImportPathSegments.join('/'); 3513af6ab5fSopenharmony_ci originalOhmUrlSegments[3] = mangledImportPath; // 3: index of standard import path in array. 3523af6ab5fSopenharmony_ci return originalOhmUrlSegments.join('&'); 3533af6ab5fSopenharmony_ci } 3543af6ab5fSopenharmony_ci 3553af6ab5fSopenharmony_ci function mangleFileName(orignalPath: string): string { 3563af6ab5fSopenharmony_ci const originalFileNameSegments: string[] = FileUtils.splitFilePath(orignalPath); 3573af6ab5fSopenharmony_ci const mangledSegments: string[] = originalFileNameSegments.map(originalSegment => mangleFileNamePart(originalSegment)); 3583af6ab5fSopenharmony_ci let mangledFileName: string = mangledSegments.join('/'); 3593af6ab5fSopenharmony_ci return mangledFileName; 3603af6ab5fSopenharmony_ci } 3613af6ab5fSopenharmony_ci 3623af6ab5fSopenharmony_ci function mangleFileNamePart(original: string): string { 3633af6ab5fSopenharmony_ci if (needToBeReserved(reservedFileNames, universalReservedFileNames, original)) { 3643af6ab5fSopenharmony_ci return original; 3653af6ab5fSopenharmony_ci } 3663af6ab5fSopenharmony_ci 3673af6ab5fSopenharmony_ci const historyName: string = historyFileNameMangledTable?.get(original); 3683af6ab5fSopenharmony_ci let mangledName: string = historyName ? historyName : globalFileNameMangledTable.get(original); 3693af6ab5fSopenharmony_ci 3703af6ab5fSopenharmony_ci while (!mangledName) { 3713af6ab5fSopenharmony_ci mangledName = generator.getName(); 3723af6ab5fSopenharmony_ci if (mangledName === original || needToBeReserved(reservedFileNames, universalReservedFileNames, mangledName)) { 3733af6ab5fSopenharmony_ci mangledName = null; 3743af6ab5fSopenharmony_ci continue; 3753af6ab5fSopenharmony_ci } 3763af6ab5fSopenharmony_ci 3773af6ab5fSopenharmony_ci let reserved: string[] = [...globalFileNameMangledTable.values()]; 3783af6ab5fSopenharmony_ci if (reserved.includes(mangledName)) { 3793af6ab5fSopenharmony_ci mangledName = null; 3803af6ab5fSopenharmony_ci continue; 3813af6ab5fSopenharmony_ci } 3823af6ab5fSopenharmony_ci 3833af6ab5fSopenharmony_ci if (historyFileNameMangledTable && [...historyFileNameMangledTable.values()].includes(mangledName)) { 3843af6ab5fSopenharmony_ci mangledName = null; 3853af6ab5fSopenharmony_ci continue; 3863af6ab5fSopenharmony_ci } 3873af6ab5fSopenharmony_ci } 3883af6ab5fSopenharmony_ci globalFileNameMangledTable.set(original, mangledName); 3893af6ab5fSopenharmony_ci return mangledName; 3903af6ab5fSopenharmony_ci } 3913af6ab5fSopenharmony_ci 3923af6ab5fSopenharmony_ci export let transformerPlugin: TransformPlugin = { 3933af6ab5fSopenharmony_ci 'name': 'renamePropertiesPlugin', 3943af6ab5fSopenharmony_ci 'order': TransformerOrder.RENAME_FILE_NAME_TRANSFORMER, 3953af6ab5fSopenharmony_ci 'createTransformerFactory': createRenameFileNameFactory 3963af6ab5fSopenharmony_ci }; 3973af6ab5fSopenharmony_ci} 3983af6ab5fSopenharmony_ci 3993af6ab5fSopenharmony_ciexport = secharmony; 4003af6ab5fSopenharmony_ci 4013af6ab5fSopenharmony_ci// typescript doesn't add the json extension. 4023af6ab5fSopenharmony_ciconst extensionOrder: string[] = ['.ets', '.ts', '.d.ets', '.d.ts', '.js']; 4033af6ab5fSopenharmony_ci 4043af6ab5fSopenharmony_cifunction tryValidateFileExisting(importPath: string): PathAndExtension | undefined { 4053af6ab5fSopenharmony_ci let fileAbsPath: string = ''; 4063af6ab5fSopenharmony_ci if (path.isAbsolute(importPath)) { 4073af6ab5fSopenharmony_ci fileAbsPath = importPath; 4083af6ab5fSopenharmony_ci } else { 4093af6ab5fSopenharmony_ci fileAbsPath = path.join(path.dirname(orignalFilePathForSearching), importPath); 4103af6ab5fSopenharmony_ci } 4113af6ab5fSopenharmony_ci 4123af6ab5fSopenharmony_ci const filePathExtensionLess: string = path.normalize(fileAbsPath); 4133af6ab5fSopenharmony_ci for (let ext of extensionOrder) { 4143af6ab5fSopenharmony_ci const targetPath = filePathExtensionLess + ext; 4153af6ab5fSopenharmony_ci if (fs.existsSync(targetPath)) { 4163af6ab5fSopenharmony_ci return {path: importPath, ext: ext}; 4173af6ab5fSopenharmony_ci } 4183af6ab5fSopenharmony_ci } 4193af6ab5fSopenharmony_ci 4203af6ab5fSopenharmony_ci // all suffixes are not matched, search this file directly. 4213af6ab5fSopenharmony_ci if (fs.existsSync(filePathExtensionLess)) { 4223af6ab5fSopenharmony_ci return { path: importPath, ext: undefined }; 4233af6ab5fSopenharmony_ci } 4243af6ab5fSopenharmony_ci return undefined; 4253af6ab5fSopenharmony_ci}