13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2024 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  ArkObfuscator,
183af6ab5fSopenharmony_ci  ObfuscationResultType,
193af6ab5fSopenharmony_ci  PropCollections,
203af6ab5fSopenharmony_ci  performancePrinter,
213af6ab5fSopenharmony_ci  renameIdentifierModule
223af6ab5fSopenharmony_ci} from './ArkObfuscator';
233af6ab5fSopenharmony_ciimport { readProjectProperties } from './common/ApiReaderForTest';
243af6ab5fSopenharmony_ciimport { FileUtils } from './utils/FileUtils';
253af6ab5fSopenharmony_ciimport { EventList } from './utils/PrinterUtils';
263af6ab5fSopenharmony_ciimport { handleReservedConfig } from './utils/TransformUtil';
273af6ab5fSopenharmony_ciimport {
283af6ab5fSopenharmony_ci  IDENTIFIER_CACHE,
293af6ab5fSopenharmony_ci  NAME_CACHE_SUFFIX,
303af6ab5fSopenharmony_ci  PROPERTY_CACHE_FILE,
313af6ab5fSopenharmony_ci  deleteLineInfoForNameString,
323af6ab5fSopenharmony_ci  getMapFromJson,
333af6ab5fSopenharmony_ci  readCache,
343af6ab5fSopenharmony_ci  writeCache
353af6ab5fSopenharmony_ci} from './utils/NameCacheUtil';
363af6ab5fSopenharmony_ci
373af6ab5fSopenharmony_ciimport * as fs from 'fs';
383af6ab5fSopenharmony_ciimport path from 'path';
393af6ab5fSopenharmony_ciimport filterFileArray from './configs/test262filename/filterFilenameList.json';
403af6ab5fSopenharmony_ciimport { UnobfuscationCollections } from './utils/CommonCollections';
413af6ab5fSopenharmony_ciimport { unobfuscationNamesObj } from './initialization/CommonObject';
423af6ab5fSopenharmony_ciimport { printUnobfuscationReasons } from './initialization/ConfigResolver';
433af6ab5fSopenharmony_ciimport { mergeSet, convertSetToArray } from './initialization/utils';
443af6ab5fSopenharmony_ci
453af6ab5fSopenharmony_ciimport type { IOptions } from './configs/IOptions';
463af6ab5fSopenharmony_ci
473af6ab5fSopenharmony_ciconst JSON_TEXT_INDENT_LENGTH: number = 2;
483af6ab5fSopenharmony_ci
493af6ab5fSopenharmony_ciinterface OutPathObj {
503af6ab5fSopenharmony_ci  outputPath: string;
513af6ab5fSopenharmony_ci  relativePath: string;
523af6ab5fSopenharmony_ci}
533af6ab5fSopenharmony_ci
543af6ab5fSopenharmony_ciexport class ArkObfuscatorForTest extends ArkObfuscator {
553af6ab5fSopenharmony_ci  // A list of source file path
563af6ab5fSopenharmony_ci  private readonly mSourceFiles: string[];
573af6ab5fSopenharmony_ci
583af6ab5fSopenharmony_ci  // Path of obfuscation configuration file.
593af6ab5fSopenharmony_ci  private readonly mConfigPath: string;
603af6ab5fSopenharmony_ci
613af6ab5fSopenharmony_ci  private mTestType: string | undefined = undefined;
623af6ab5fSopenharmony_ci
633af6ab5fSopenharmony_ci  constructor(sourceFiles?: string[], configPath?: string) {
643af6ab5fSopenharmony_ci    super();
653af6ab5fSopenharmony_ci    this.mSourceFiles = sourceFiles;
663af6ab5fSopenharmony_ci    this.mConfigPath = configPath;
673af6ab5fSopenharmony_ci  }
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci  public get configPath(): string {
703af6ab5fSopenharmony_ci    return this.mConfigPath;
713af6ab5fSopenharmony_ci  }
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci  public setTestType(testType: string | undefined): void {
743af6ab5fSopenharmony_ci    this.mTestType = testType;
753af6ab5fSopenharmony_ci  }
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ci  /**
783af6ab5fSopenharmony_ci   * init ArkObfuscator according to user config
793af6ab5fSopenharmony_ci   * should be called after constructor
803af6ab5fSopenharmony_ci   */
813af6ab5fSopenharmony_ci  public init(config: IOptions | undefined): boolean {
823af6ab5fSopenharmony_ci    if (!config) {
833af6ab5fSopenharmony_ci        console.error('obfuscation config file is not found and no given config.');
843af6ab5fSopenharmony_ci        return false;
853af6ab5fSopenharmony_ci    }
863af6ab5fSopenharmony_ci    UnobfuscationCollections.printKeptName = config.mUnobfuscationOption?.mPrintKeptNames;
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    handleReservedConfig(config, 'mNameObfuscation', 'mReservedProperties', 'mUniversalReservedProperties');
893af6ab5fSopenharmony_ci    handleReservedConfig(config, 'mNameObfuscation', 'mReservedToplevelNames', 'mUniversalReservedToplevelNames');
903af6ab5fSopenharmony_ci    return super.init(config);
913af6ab5fSopenharmony_ci  }
923af6ab5fSopenharmony_ci
933af6ab5fSopenharmony_ci  /**
943af6ab5fSopenharmony_ci   * Obfuscate all the source files.
953af6ab5fSopenharmony_ci   */
963af6ab5fSopenharmony_ci  public async obfuscateFiles(): Promise<void> {
973af6ab5fSopenharmony_ci    if (!path.isAbsolute(this.mCustomProfiles.mOutputDir)) {
983af6ab5fSopenharmony_ci      this.mCustomProfiles.mOutputDir = path.join(path.dirname(this.mConfigPath), this.mCustomProfiles.mOutputDir);
993af6ab5fSopenharmony_ci    }
1003af6ab5fSopenharmony_ci
1013af6ab5fSopenharmony_ci    performancePrinter?.filesPrinter?.startEvent(EventList.ALL_FILES_OBFUSCATION);
1023af6ab5fSopenharmony_ci    readProjectProperties(this.mSourceFiles, structuredClone(this.mCustomProfiles), this);
1033af6ab5fSopenharmony_ci    const propertyCachePath = path.join(this.mCustomProfiles.mOutputDir, 
1043af6ab5fSopenharmony_ci                                        path.basename(this.mSourceFiles[0])); // Get dir name
1053af6ab5fSopenharmony_ci    this.readPropertyCache(propertyCachePath);
1063af6ab5fSopenharmony_ci
1073af6ab5fSopenharmony_ci    // support directory and file obfuscate
1083af6ab5fSopenharmony_ci    for (const sourcePath of this.mSourceFiles) {
1093af6ab5fSopenharmony_ci      if (!fs.existsSync(sourcePath)) {
1103af6ab5fSopenharmony_ci        console.error(`File ${FileUtils.getFileName(sourcePath)} is not found.`);
1113af6ab5fSopenharmony_ci        return;
1123af6ab5fSopenharmony_ci      }
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci      if (fs.lstatSync(sourcePath).isFile()) {
1153af6ab5fSopenharmony_ci        await this.obfuscateFile(sourcePath, this.mCustomProfiles.mOutputDir);
1163af6ab5fSopenharmony_ci        continue;
1173af6ab5fSopenharmony_ci      }
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_ci      const dirPrefix: string = FileUtils.getPrefix(sourcePath);
1203af6ab5fSopenharmony_ci      await this.obfuscateDir(sourcePath, dirPrefix);
1213af6ab5fSopenharmony_ci    }
1223af6ab5fSopenharmony_ci
1233af6ab5fSopenharmony_ci    if (this.mCustomProfiles.mUnobfuscationOption?.mPrintKeptNames) {
1243af6ab5fSopenharmony_ci      const dir = path.dirname(this.mSourceFiles[0]).replace('grammar', 'local');
1253af6ab5fSopenharmony_ci      const basename = path.basename(this.mSourceFiles[0]);
1263af6ab5fSopenharmony_ci      let printKeptNamesPath = path.join(dir, basename, '/keptNames.unobf.json');
1273af6ab5fSopenharmony_ci      let printWhitelistPath = path.join(dir, basename, '/whitelist.unobf.json');
1283af6ab5fSopenharmony_ci      this.writeUnobfuscationContentForTest(printKeptNamesPath, printWhitelistPath);
1293af6ab5fSopenharmony_ci    }
1303af6ab5fSopenharmony_ci
1313af6ab5fSopenharmony_ci    this.producePropertyCache(propertyCachePath);
1323af6ab5fSopenharmony_ci    performancePrinter?.filesPrinter?.endEvent(EventList.ALL_FILES_OBFUSCATION);
1333af6ab5fSopenharmony_ci    performancePrinter?.timeSumPrinter?.print('Sum up time of processes');
1343af6ab5fSopenharmony_ci    performancePrinter?.timeSumPrinter?.summarizeEventDuration();
1353af6ab5fSopenharmony_ci  }
1363af6ab5fSopenharmony_ci
1373af6ab5fSopenharmony_ci  private writeUnobfuscationContentForTest(printKeptNamesPath: string, printWhitelistPath: string): void {
1383af6ab5fSopenharmony_ci    printUnobfuscationReasons('', printKeptNamesPath);
1393af6ab5fSopenharmony_ci    this.printWhitelist(this.mCustomProfiles, printWhitelistPath);
1403af6ab5fSopenharmony_ci  }
1413af6ab5fSopenharmony_ci
1423af6ab5fSopenharmony_ci  private printWhitelist(obfuscationOptions: IOptions, printPath: string): void {
1433af6ab5fSopenharmony_ci    const nameOption = obfuscationOptions.mNameObfuscation;
1443af6ab5fSopenharmony_ci    const enableToplevel = nameOption.mTopLevel;
1453af6ab5fSopenharmony_ci    const enableProperty = nameOption.mRenameProperties;
1463af6ab5fSopenharmony_ci    const enableStringProp = !nameOption.mKeepStringProperty;
1473af6ab5fSopenharmony_ci    const enableExport = obfuscationOptions.mExportObfuscation;
1483af6ab5fSopenharmony_ci    const reservedConfToplevelArrary = nameOption.mReservedToplevelNames ?? [];
1493af6ab5fSopenharmony_ci    const reservedConfPropertyArray = nameOption.mReservedProperties ?? [];
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_ci    let whitelistObj = {
1523af6ab5fSopenharmony_ci      lang: [],
1533af6ab5fSopenharmony_ci      conf: [],
1543af6ab5fSopenharmony_ci      struct: [],
1553af6ab5fSopenharmony_ci      exported: [],
1563af6ab5fSopenharmony_ci      strProp: []
1573af6ab5fSopenharmony_ci    };
1583af6ab5fSopenharmony_ci  
1593af6ab5fSopenharmony_ci    if (enableExport || enableProperty) {
1603af6ab5fSopenharmony_ci      const languageSet = mergeSet(UnobfuscationCollections.reservedLangForProperty, UnobfuscationCollections.reservedLangForTopLevel);
1613af6ab5fSopenharmony_ci      whitelistObj.lang = convertSetToArray(languageSet);
1623af6ab5fSopenharmony_ci      const strutSet = UnobfuscationCollections.reservedStruct;
1633af6ab5fSopenharmony_ci      whitelistObj.struct = convertSetToArray(strutSet);
1643af6ab5fSopenharmony_ci      const exportSet = mergeSet(UnobfuscationCollections.reservedExportName, UnobfuscationCollections.reservedExportNameAndProp);
1653af6ab5fSopenharmony_ci      whitelistObj.exported = convertSetToArray(exportSet);
1663af6ab5fSopenharmony_ci      if (!enableStringProp) {
1673af6ab5fSopenharmony_ci        const stringSet = UnobfuscationCollections.reservedStrProp;
1683af6ab5fSopenharmony_ci        whitelistObj.strProp = convertSetToArray(stringSet);
1693af6ab5fSopenharmony_ci      }
1703af6ab5fSopenharmony_ci    }
1713af6ab5fSopenharmony_ci  
1723af6ab5fSopenharmony_ci    const hasPropertyConfig = enableProperty && reservedConfPropertyArray?.length > 0;
1733af6ab5fSopenharmony_ci    const hasTopLevelConfig = enableToplevel && reservedConfToplevelArrary?.length > 0;
1743af6ab5fSopenharmony_ci    if (hasPropertyConfig) {
1753af6ab5fSopenharmony_ci      // if -enable-property-obfuscation and -enable-toplevel-obfuscation,
1763af6ab5fSopenharmony_ci      // the mReservedToplevelNames has already been merged into the mReservedToplevelNames.
1773af6ab5fSopenharmony_ci      whitelistObj.conf.push(...reservedConfPropertyArray);
1783af6ab5fSopenharmony_ci      this.handleUniversalReservedList(nameOption.mUniversalReservedProperties, whitelistObj.conf);
1793af6ab5fSopenharmony_ci    } else if (hasTopLevelConfig) {
1803af6ab5fSopenharmony_ci      whitelistObj.conf.push(...reservedConfToplevelArrary);
1813af6ab5fSopenharmony_ci      this.handleUniversalReservedList(nameOption.mUniversalReservedToplevelNames, whitelistObj.conf);
1823af6ab5fSopenharmony_ci    }
1833af6ab5fSopenharmony_ci  
1843af6ab5fSopenharmony_ci    let whitelistContent = JSON.stringify(whitelistObj, null, 2);
1853af6ab5fSopenharmony_ci    if (!fs.existsSync(path.dirname(printPath))) {
1863af6ab5fSopenharmony_ci      fs.mkdirSync(path.dirname(printPath), { recursive: true });
1873af6ab5fSopenharmony_ci    }
1883af6ab5fSopenharmony_ci    fs.writeFileSync(printPath, whitelistContent);
1893af6ab5fSopenharmony_ci  }
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci  private handleUniversalReservedList(universalList: RegExp[] | undefined, configArray: string[]): void {
1923af6ab5fSopenharmony_ci    if (universalList?.length > 0) {
1933af6ab5fSopenharmony_ci      universalList.forEach((value) => {
1943af6ab5fSopenharmony_ci        const originalString = UnobfuscationCollections.reservedWildcardMap.get(value);
1953af6ab5fSopenharmony_ci        if (originalString) {
1963af6ab5fSopenharmony_ci          configArray.push(originalString);
1973af6ab5fSopenharmony_ci        }
1983af6ab5fSopenharmony_ci      });
1993af6ab5fSopenharmony_ci    }
2003af6ab5fSopenharmony_ci  }
2013af6ab5fSopenharmony_ci
2023af6ab5fSopenharmony_ci  /**
2033af6ab5fSopenharmony_ci   * obfuscate directory
2043af6ab5fSopenharmony_ci   * @private
2053af6ab5fSopenharmony_ci   */
2063af6ab5fSopenharmony_ci  private async obfuscateDir(dirName: string, dirPrefix: string): Promise<void> {
2073af6ab5fSopenharmony_ci    const currentDir: string = FileUtils.getPathWithoutPrefix(dirName, dirPrefix);
2083af6ab5fSopenharmony_ci    let newDir: string = this.mCustomProfiles.mOutputDir;
2093af6ab5fSopenharmony_ci    // there is no need to create directory because the directory names will be obfuscated.
2103af6ab5fSopenharmony_ci    if (!this.mCustomProfiles.mRenameFileName?.mEnable) {
2113af6ab5fSopenharmony_ci      newDir = path.join(this.mCustomProfiles.mOutputDir, currentDir);
2123af6ab5fSopenharmony_ci    }
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_ci    const fileNames: string[] = fs.readdirSync(dirName);
2153af6ab5fSopenharmony_ci    for (let fileName of fileNames) {
2163af6ab5fSopenharmony_ci      const filePath: string = path.join(dirName, fileName);
2173af6ab5fSopenharmony_ci      if (fs.lstatSync(filePath).isFile()) {
2183af6ab5fSopenharmony_ci        await this.obfuscateFile(filePath, newDir);
2193af6ab5fSopenharmony_ci        continue;
2203af6ab5fSopenharmony_ci      }
2213af6ab5fSopenharmony_ci
2223af6ab5fSopenharmony_ci      await this.obfuscateDir(filePath, dirPrefix);
2233af6ab5fSopenharmony_ci    }
2243af6ab5fSopenharmony_ci  }
2253af6ab5fSopenharmony_ci
2263af6ab5fSopenharmony_ci  /**
2273af6ab5fSopenharmony_ci   * Obfuscate single source file with path provided
2283af6ab5fSopenharmony_ci   *
2293af6ab5fSopenharmony_ci   * @param sourceFilePath single source file path
2303af6ab5fSopenharmony_ci   * @param outputDir
2313af6ab5fSopenharmony_ci   */
2323af6ab5fSopenharmony_ci  public async obfuscateFile(sourceFilePath: string, outputDir: string): Promise<void> {
2333af6ab5fSopenharmony_ci    const fileName: string = FileUtils.getFileName(sourceFilePath);
2343af6ab5fSopenharmony_ci    const config = this.mCustomProfiles;
2353af6ab5fSopenharmony_ci    if (this.isObfsIgnoreFile(fileName)) {
2363af6ab5fSopenharmony_ci      fs.mkdirSync(outputDir, { recursive: true });
2373af6ab5fSopenharmony_ci      fs.copyFileSync(sourceFilePath, path.join(outputDir, fileName));
2383af6ab5fSopenharmony_ci      return;
2393af6ab5fSopenharmony_ci    }
2403af6ab5fSopenharmony_ci
2413af6ab5fSopenharmony_ci    const test262Filename = this.getPathAfterTest262SecondLevel(sourceFilePath);
2423af6ab5fSopenharmony_ci    const isFileInArray = filterFileArray.includes(test262Filename);
2433af6ab5fSopenharmony_ci    // To skip the path where 262 test will fail.
2443af6ab5fSopenharmony_ci    if (isFileInArray) {
2453af6ab5fSopenharmony_ci      return;
2463af6ab5fSopenharmony_ci    }
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_ci    // Add the whitelist of file name obfuscation for ut.
2493af6ab5fSopenharmony_ci    if (config.mRenameFileName?.mEnable) {
2503af6ab5fSopenharmony_ci      const reservedArray = config.mRenameFileName.mReservedFileNames;
2513af6ab5fSopenharmony_ci      FileUtils.collectPathReservedString(this.mConfigPath, reservedArray);
2523af6ab5fSopenharmony_ci    }
2533af6ab5fSopenharmony_ci    let content: string = FileUtils.readFile(sourceFilePath);
2543af6ab5fSopenharmony_ci    this.readNameCache(sourceFilePath, outputDir);
2553af6ab5fSopenharmony_ci    performancePrinter?.filesPrinter?.startEvent(sourceFilePath);
2563af6ab5fSopenharmony_ci    let filePath = { buildFilePath: sourceFilePath, relativeFilePath: sourceFilePath };
2573af6ab5fSopenharmony_ci    const mixedInfo: ObfuscationResultType = await this.obfuscate(content, filePath);
2583af6ab5fSopenharmony_ci    performancePrinter?.filesPrinter?.endEvent(sourceFilePath, undefined, true);
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_ci    if (this.mWriteOriginalFile && mixedInfo) {
2613af6ab5fSopenharmony_ci      // Write the obfuscated content directly to orignal file.
2623af6ab5fSopenharmony_ci      fs.writeFileSync(sourceFilePath, mixedInfo.content);
2633af6ab5fSopenharmony_ci      return;
2643af6ab5fSopenharmony_ci    }
2653af6ab5fSopenharmony_ci    if (outputDir && mixedInfo) {
2663af6ab5fSopenharmony_ci      const outputPathObj: OutPathObj = this.getOutputPath(sourceFilePath, mixedInfo);
2673af6ab5fSopenharmony_ci      this.writeContent(outputPathObj.outputPath, outputPathObj.relativePath, mixedInfo);
2683af6ab5fSopenharmony_ci    }
2693af6ab5fSopenharmony_ci  }
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci  private getOutputPath(sourceFilePath: string, mixedInfo: ObfuscationResultType): OutPathObj {
2723af6ab5fSopenharmony_ci    const config = this.mCustomProfiles;
2733af6ab5fSopenharmony_ci    if (this.mTestType === 'grammar') {
2743af6ab5fSopenharmony_ci      const testCasesRootPath = path.join(__dirname, '../', 'test/grammar');
2753af6ab5fSopenharmony_ci      let relativePath = '';
2763af6ab5fSopenharmony_ci      if (config.mRenameFileName?.mEnable && mixedInfo.filePath) {
2773af6ab5fSopenharmony_ci        relativePath = mixedInfo.filePath.replace(testCasesRootPath, '');
2783af6ab5fSopenharmony_ci      } else {
2793af6ab5fSopenharmony_ci        relativePath = sourceFilePath.replace(testCasesRootPath, '');
2803af6ab5fSopenharmony_ci      }
2813af6ab5fSopenharmony_ci      const resultPath = path.join(config.mOutputDir, relativePath);
2823af6ab5fSopenharmony_ci      return {outputPath: resultPath, relativePath: relativePath};
2833af6ab5fSopenharmony_ci    } else if (this.mTestType === 'combinations') {
2843af6ab5fSopenharmony_ci      const outputDir = this.mCustomProfiles.mOutputDir;
2853af6ab5fSopenharmony_ci      const directory = outputDir.substring(0, outputDir.lastIndexOf('/') + 1);
2863af6ab5fSopenharmony_ci      const sourceBaseDir = directory.replace('local/combinations', 'combinations');
2873af6ab5fSopenharmony_ci      const relativePath = sourceFilePath.replace(sourceBaseDir, '');
2883af6ab5fSopenharmony_ci      const resultPath = path.join(this.mCustomProfiles.mOutputDir, relativePath);
2893af6ab5fSopenharmony_ci      return {outputPath: resultPath, relativePath: relativePath};
2903af6ab5fSopenharmony_ci    } else {
2913af6ab5fSopenharmony_ci      throw new Error('Please select a test type');
2923af6ab5fSopenharmony_ci    }
2933af6ab5fSopenharmony_ci  }
2943af6ab5fSopenharmony_ci
2953af6ab5fSopenharmony_ci  private writeContent(outputPath: string, relativePath: string, mixedInfo: ObfuscationResultType): void {
2963af6ab5fSopenharmony_ci    if (!fs.existsSync(path.dirname(outputPath))) {
2973af6ab5fSopenharmony_ci      fs.mkdirSync(path.dirname(outputPath), { recursive: true });
2983af6ab5fSopenharmony_ci    }
2993af6ab5fSopenharmony_ci
3003af6ab5fSopenharmony_ci    fs.writeFileSync(outputPath, mixedInfo.content);
3013af6ab5fSopenharmony_ci
3023af6ab5fSopenharmony_ci    if (this.mCustomProfiles.mEnableSourceMap && mixedInfo.sourceMap) {
3033af6ab5fSopenharmony_ci      fs.writeFileSync(path.join(outputPath + '.map'),
3043af6ab5fSopenharmony_ci        JSON.stringify(mixedInfo.sourceMap, null, JSON_TEXT_INDENT_LENGTH));
3053af6ab5fSopenharmony_ci    }
3063af6ab5fSopenharmony_ci
3073af6ab5fSopenharmony_ci    if (this.mCustomProfiles.mEnableNameCache && this.mCustomProfiles.mEnableNameCache) {
3083af6ab5fSopenharmony_ci      this.produceNameCache(mixedInfo.nameCache, outputPath);
3093af6ab5fSopenharmony_ci    }
3103af6ab5fSopenharmony_ci
3113af6ab5fSopenharmony_ci    if (mixedInfo.unobfuscationNameMap) {
3123af6ab5fSopenharmony_ci      this.loadunobfuscationNameMap(mixedInfo, relativePath);
3133af6ab5fSopenharmony_ci    }
3143af6ab5fSopenharmony_ci  }
3153af6ab5fSopenharmony_ci
3163af6ab5fSopenharmony_ci  private loadunobfuscationNameMap(mixedInfo: ObfuscationResultType, relativePath: string): void {
3173af6ab5fSopenharmony_ci    let arrayObject: Record<string, string[]> = {};
3183af6ab5fSopenharmony_ci    // The type of unobfuscationNameMap's value is Set, convert Set to Array.
3193af6ab5fSopenharmony_ci    mixedInfo.unobfuscationNameMap.forEach((value: Set<string>, key: string) => {
3203af6ab5fSopenharmony_ci      let array: string[] = Array.from(value);
3213af6ab5fSopenharmony_ci      arrayObject[key] = array;
3223af6ab5fSopenharmony_ci    });
3233af6ab5fSopenharmony_ci    unobfuscationNamesObj[relativePath] = arrayObject;
3243af6ab5fSopenharmony_ci  }
3253af6ab5fSopenharmony_ci
3263af6ab5fSopenharmony_ci  private getPathAfterTest262SecondLevel(fullPath: string): string {
3273af6ab5fSopenharmony_ci    const pathParts = fullPath.split('/');
3283af6ab5fSopenharmony_ci    const dataIndex = pathParts.indexOf('test262');
3293af6ab5fSopenharmony_ci    // 2: Calculate the index of the second-level directory after 'test262'
3303af6ab5fSopenharmony_ci    const secondLevelIndex = dataIndex + 2;
3313af6ab5fSopenharmony_ci
3323af6ab5fSopenharmony_ci    if (dataIndex !== -1 && secondLevelIndex < pathParts.length) {
3333af6ab5fSopenharmony_ci      return pathParts.slice(secondLevelIndex).join('/');
3343af6ab5fSopenharmony_ci    }
3353af6ab5fSopenharmony_ci  
3363af6ab5fSopenharmony_ci    return fullPath;
3373af6ab5fSopenharmony_ci  }
3383af6ab5fSopenharmony_ci
3393af6ab5fSopenharmony_ci  private produceNameCache(namecache: { [k: string]: string | {} }, resultPath: string): void {
3403af6ab5fSopenharmony_ci    const nameCachePath: string = resultPath + NAME_CACHE_SUFFIX;
3413af6ab5fSopenharmony_ci    fs.writeFileSync(nameCachePath, JSON.stringify(namecache, null, JSON_TEXT_INDENT_LENGTH));
3423af6ab5fSopenharmony_ci  }
3433af6ab5fSopenharmony_ci
3443af6ab5fSopenharmony_ci  private readNameCache(sourceFile: string, outputDir: string): void {
3453af6ab5fSopenharmony_ci    if (!this.mCustomProfiles.mNameObfuscation?.mEnable || !this.mCustomProfiles.mEnableNameCache) {
3463af6ab5fSopenharmony_ci      return;
3473af6ab5fSopenharmony_ci    }
3483af6ab5fSopenharmony_ci
3493af6ab5fSopenharmony_ci    const nameCachePath: string = path.join(outputDir, FileUtils.getFileName(sourceFile) + NAME_CACHE_SUFFIX);
3503af6ab5fSopenharmony_ci    const nameCache: Object = readCache(nameCachePath);
3513af6ab5fSopenharmony_ci    let historyNameCache = new Map<string, string>();
3523af6ab5fSopenharmony_ci    let identifierCache = nameCache ? Reflect.get(nameCache, IDENTIFIER_CACHE) : undefined;
3533af6ab5fSopenharmony_ci    deleteLineInfoForNameString(historyNameCache, identifierCache);
3543af6ab5fSopenharmony_ci
3553af6ab5fSopenharmony_ci    renameIdentifierModule.historyNameCache = historyNameCache;
3563af6ab5fSopenharmony_ci  }
3573af6ab5fSopenharmony_ci
3583af6ab5fSopenharmony_ci  private producePropertyCache(outputDir: string): void {
3593af6ab5fSopenharmony_ci    if (this.mCustomProfiles.mNameObfuscation &&
3603af6ab5fSopenharmony_ci      this.mCustomProfiles.mNameObfuscation.mRenameProperties &&
3613af6ab5fSopenharmony_ci      this.mCustomProfiles.mEnableNameCache) {
3623af6ab5fSopenharmony_ci      const propertyCachePath: string = path.join(outputDir, PROPERTY_CACHE_FILE);
3633af6ab5fSopenharmony_ci      writeCache(PropCollections.globalMangledTable, propertyCachePath);
3643af6ab5fSopenharmony_ci    }
3653af6ab5fSopenharmony_ci  }
3663af6ab5fSopenharmony_ci
3673af6ab5fSopenharmony_ci  private readPropertyCache(outputDir: string): void {
3683af6ab5fSopenharmony_ci    if (!this.mCustomProfiles.mNameObfuscation?.mRenameProperties || !this.mCustomProfiles.mEnableNameCache) {
3693af6ab5fSopenharmony_ci      return;
3703af6ab5fSopenharmony_ci    }
3713af6ab5fSopenharmony_ci
3723af6ab5fSopenharmony_ci    const propertyCachePath: string = path.join(outputDir, PROPERTY_CACHE_FILE);
3733af6ab5fSopenharmony_ci    const propertyCache: Object = readCache(propertyCachePath);
3743af6ab5fSopenharmony_ci    if (!propertyCache) {
3753af6ab5fSopenharmony_ci      return;
3763af6ab5fSopenharmony_ci    }
3773af6ab5fSopenharmony_ci
3783af6ab5fSopenharmony_ci    PropCollections.historyMangledTable = getMapFromJson(propertyCache);
3793af6ab5fSopenharmony_ci  }
3803af6ab5fSopenharmony_ci}