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 fs from 'fs';
173af6ab5fSopenharmony_ciimport path from 'path';
183af6ab5fSopenharmony_ciimport JSON5 from 'json5';
193af6ab5fSopenharmony_ci
203af6ab5fSopenharmony_ciimport type * as ts from 'typescript';
213af6ab5fSopenharmony_ci
223af6ab5fSopenharmony_ciimport { FileUtils } from '../utils/FileUtils';
233af6ab5fSopenharmony_ciimport {
243af6ab5fSopenharmony_ci  type ReservedNameInfo,
253af6ab5fSopenharmony_ci  ApiExtractor,
263af6ab5fSopenharmony_ci  containWildcards,
273af6ab5fSopenharmony_ci  getMapFromJson,
283af6ab5fSopenharmony_ci  performancePrinter,
293af6ab5fSopenharmony_ci  PropCollections,
303af6ab5fSopenharmony_ci  renameFileNameModule,
313af6ab5fSopenharmony_ci  separateUniversalReservedItem,
323af6ab5fSopenharmony_ci  wildcardTransformer,
333af6ab5fSopenharmony_ci} from '../ArkObfuscator';
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_ciimport { isDebug, isFileExist, sortAndDeduplicateStringArr, mergeSet, convertSetToArray } from './utils';
363af6ab5fSopenharmony_ciimport { nameCacheMap, yellow, unobfuscationNamesObj } from './CommonObject';
373af6ab5fSopenharmony_ciimport { historyUnobfuscatedPropMap } from './Initializer';
383af6ab5fSopenharmony_ciimport { LocalVariableCollections, UnobfuscationCollections } from '../utils/CommonCollections';
393af6ab5fSopenharmony_ciimport { INameObfuscationOption } from '../configs/INameObfuscationOption';
403af6ab5fSopenharmony_ciimport { WhitelistType } from '../utils/TransformUtil';
413af6ab5fSopenharmony_ci
423af6ab5fSopenharmony_cienum OptionType {
433af6ab5fSopenharmony_ci  NONE,
443af6ab5fSopenharmony_ci  KEEP,
453af6ab5fSopenharmony_ci  KEEP_DTS,
463af6ab5fSopenharmony_ci  KEEP_GLOBAL_NAME,
473af6ab5fSopenharmony_ci  KEEP_PROPERTY_NAME,
483af6ab5fSopenharmony_ci  KEEP_FILE_NAME,
493af6ab5fSopenharmony_ci  KEEP_COMMENTS,
503af6ab5fSopenharmony_ci  DISABLE_OBFUSCATION,
513af6ab5fSopenharmony_ci  ENABLE_PROPERTY_OBFUSCATION,
523af6ab5fSopenharmony_ci  ENABLE_STRING_PROPERTY_OBFUSCATION,
533af6ab5fSopenharmony_ci  ENABLE_TOPLEVEL_OBFUSCATION,
543af6ab5fSopenharmony_ci  ENABLE_FILENAME_OBFUSCATION,
553af6ab5fSopenharmony_ci  ENABLE_EXPORT_OBFUSCATION,
563af6ab5fSopenharmony_ci  COMPACT,
573af6ab5fSopenharmony_ci  REMOVE_LOG,
583af6ab5fSopenharmony_ci  REMOVE_COMMENTS,
593af6ab5fSopenharmony_ci  PRINT_NAMECACHE,
603af6ab5fSopenharmony_ci  PRINT_KEPT_NAMES,
613af6ab5fSopenharmony_ci  APPLY_NAMECACHE,
623af6ab5fSopenharmony_ci}
633af6ab5fSopenharmony_ciexport { OptionType as OptionTypeForTest };
643af6ab5fSopenharmony_ci
653af6ab5fSopenharmony_citype SystemApiContent = {
663af6ab5fSopenharmony_ci  ReservedPropertyNames?: string[];
673af6ab5fSopenharmony_ci  ReservedGlobalNames?: string[];
683af6ab5fSopenharmony_ci  ReservedLocalNames?: string[];
693af6ab5fSopenharmony_ci};
703af6ab5fSopenharmony_ci
713af6ab5fSopenharmony_ci/* ObConfig's properties:
723af6ab5fSopenharmony_ci *   ruleOptions: {
733af6ab5fSopenharmony_ci *    enable: boolean
743af6ab5fSopenharmony_ci *    rules: string[]
753af6ab5fSopenharmony_ci *   }
763af6ab5fSopenharmony_ci *   consumerRules: string[]
773af6ab5fSopenharmony_ci *
783af6ab5fSopenharmony_ci * ObfuscationConfig's properties:
793af6ab5fSopenharmony_ci *   selfConfig: ObConfig
803af6ab5fSopenharmony_ci *   dependencies: { libraries: ObConfig[], hars: string[] }
813af6ab5fSopenharmony_ci *   sdkApis: string[]
823af6ab5fSopenharmony_ci *   obfuscationCacheDir: string
833af6ab5fSopenharmony_ci *   exportRulePath: string
843af6ab5fSopenharmony_ci */
853af6ab5fSopenharmony_ciclass ObOptions {
863af6ab5fSopenharmony_ci  disableObfuscation: boolean = false;
873af6ab5fSopenharmony_ci  enablePropertyObfuscation: boolean = false;
883af6ab5fSopenharmony_ci  enableStringPropertyObfuscation: boolean = false;
893af6ab5fSopenharmony_ci  enableToplevelObfuscation: boolean = false;
903af6ab5fSopenharmony_ci  enableFileNameObfuscation: boolean = false;
913af6ab5fSopenharmony_ci  enableExportObfuscation: boolean = false;
923af6ab5fSopenharmony_ci  printKeptNames: boolean = false;
933af6ab5fSopenharmony_ci  removeComments: boolean = false;
943af6ab5fSopenharmony_ci  compact: boolean = false;
953af6ab5fSopenharmony_ci  removeLog: boolean = false;
963af6ab5fSopenharmony_ci  printNameCache: string = '';
973af6ab5fSopenharmony_ci  printKeptNamesPath: string = '';
983af6ab5fSopenharmony_ci  applyNameCache: string = '';
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci  merge(other: ObOptions): void {
1013af6ab5fSopenharmony_ci    this.disableObfuscation = this.disableObfuscation || other.disableObfuscation;
1023af6ab5fSopenharmony_ci    this.enablePropertyObfuscation = this.enablePropertyObfuscation || other.enablePropertyObfuscation;
1033af6ab5fSopenharmony_ci    this.enableToplevelObfuscation = this.enableToplevelObfuscation || other.enableToplevelObfuscation;
1043af6ab5fSopenharmony_ci    this.enableStringPropertyObfuscation =
1053af6ab5fSopenharmony_ci      this.enableStringPropertyObfuscation || other.enableStringPropertyObfuscation;
1063af6ab5fSopenharmony_ci    this.removeComments = this.removeComments || other.removeComments;
1073af6ab5fSopenharmony_ci    this.compact = this.compact || other.compact;
1083af6ab5fSopenharmony_ci    this.removeLog = this.removeLog || other.removeLog;
1093af6ab5fSopenharmony_ci    this.enableFileNameObfuscation = this.enableFileNameObfuscation || other.enableFileNameObfuscation;
1103af6ab5fSopenharmony_ci    this.enableExportObfuscation = this.enableExportObfuscation || other.enableExportObfuscation;
1113af6ab5fSopenharmony_ci    if (other.printNameCache.length > 0) {
1123af6ab5fSopenharmony_ci      this.printNameCache = other.printNameCache;
1133af6ab5fSopenharmony_ci    }
1143af6ab5fSopenharmony_ci    if (other.printKeptNamesPath.length > 0) {
1153af6ab5fSopenharmony_ci      this.printKeptNamesPath = other.printKeptNamesPath;
1163af6ab5fSopenharmony_ci    }
1173af6ab5fSopenharmony_ci    if (other.applyNameCache.length > 0) {
1183af6ab5fSopenharmony_ci      this.applyNameCache = other.applyNameCache;
1193af6ab5fSopenharmony_ci    }
1203af6ab5fSopenharmony_ci  }
1213af6ab5fSopenharmony_ci}
1223af6ab5fSopenharmony_ciexport const ObOptionsForTest = ObOptions;
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ciexport class MergedConfig {
1253af6ab5fSopenharmony_ci  options: ObOptions = new ObOptions();
1263af6ab5fSopenharmony_ci  reservedPropertyNames: string[] = [];
1273af6ab5fSopenharmony_ci  reservedGlobalNames: string[] = [];
1283af6ab5fSopenharmony_ci  reservedNames: string[] = [];
1293af6ab5fSopenharmony_ci  reservedFileNames: string[] = [];
1303af6ab5fSopenharmony_ci  keepComments: string[] = [];
1313af6ab5fSopenharmony_ci  keepSourceOfPaths: string[] = []; // The file path or folder path configured by the developer.
1323af6ab5fSopenharmony_ci  universalReservedPropertyNames: RegExp[] = []; // Support reserved property names contain wildcards.
1333af6ab5fSopenharmony_ci  universalReservedGlobalNames: RegExp[] = []; // Support reserved global names contain wildcards.
1343af6ab5fSopenharmony_ci  keepUniversalPaths: RegExp[] = []; // Support reserved paths contain wildcards.
1353af6ab5fSopenharmony_ci  excludeUniversalPaths: RegExp[] = []; // Support excluded paths contain wildcards.
1363af6ab5fSopenharmony_ci  excludePathSet: Set<string> = new Set();
1373af6ab5fSopenharmony_ci
1383af6ab5fSopenharmony_ci  merge(other: MergedConfig): void {
1393af6ab5fSopenharmony_ci    this.options.merge(other.options);
1403af6ab5fSopenharmony_ci    this.reservedPropertyNames.push(...other.reservedPropertyNames);
1413af6ab5fSopenharmony_ci    this.reservedGlobalNames.push(...other.reservedGlobalNames);
1423af6ab5fSopenharmony_ci    this.reservedFileNames.push(...other.reservedFileNames);
1433af6ab5fSopenharmony_ci    this.keepComments.push(...other.keepComments);
1443af6ab5fSopenharmony_ci    this.keepSourceOfPaths.push(...other.keepSourceOfPaths);
1453af6ab5fSopenharmony_ci    this.keepUniversalPaths.push(...other.keepUniversalPaths);
1463af6ab5fSopenharmony_ci    this.excludeUniversalPaths.push(...other.excludeUniversalPaths);
1473af6ab5fSopenharmony_ci    other.excludePathSet.forEach((excludePath) => {
1483af6ab5fSopenharmony_ci      this.excludePathSet.add(excludePath);
1493af6ab5fSopenharmony_ci    });
1503af6ab5fSopenharmony_ci  }
1513af6ab5fSopenharmony_ci
1523af6ab5fSopenharmony_ci  sortAndDeduplicate(): void {
1533af6ab5fSopenharmony_ci    this.reservedPropertyNames = sortAndDeduplicateStringArr(this.reservedPropertyNames);
1543af6ab5fSopenharmony_ci    this.reservedGlobalNames = sortAndDeduplicateStringArr(this.reservedGlobalNames);
1553af6ab5fSopenharmony_ci    this.reservedFileNames = sortAndDeduplicateStringArr(this.reservedFileNames);
1563af6ab5fSopenharmony_ci    this.keepComments = sortAndDeduplicateStringArr(this.keepComments);
1573af6ab5fSopenharmony_ci    this.keepSourceOfPaths = sortAndDeduplicateStringArr(this.keepSourceOfPaths);
1583af6ab5fSopenharmony_ci  }
1593af6ab5fSopenharmony_ci
1603af6ab5fSopenharmony_ci  serializeMergedConfig(): string {
1613af6ab5fSopenharmony_ci    let resultStr: string = '';
1623af6ab5fSopenharmony_ci    const keys = Object.keys(this.options);
1633af6ab5fSopenharmony_ci    for (const key of keys) {
1643af6ab5fSopenharmony_ci      // skip the export of some switches.
1653af6ab5fSopenharmony_ci      if (this.options[key] === true && ObConfigResolver.exportedSwitchMap.has(String(key))) {
1663af6ab5fSopenharmony_ci        resultStr += ObConfigResolver.exportedSwitchMap.get(String(key)) + '\n';
1673af6ab5fSopenharmony_ci      }
1683af6ab5fSopenharmony_ci    }
1693af6ab5fSopenharmony_ci
1703af6ab5fSopenharmony_ci    if (this.reservedGlobalNames.length > 0) {
1713af6ab5fSopenharmony_ci      resultStr += ObConfigResolver.KEEP_GLOBAL_NAME + '\n';
1723af6ab5fSopenharmony_ci      this.reservedGlobalNames.forEach((item) => {
1733af6ab5fSopenharmony_ci        resultStr += item + '\n';
1743af6ab5fSopenharmony_ci      });
1753af6ab5fSopenharmony_ci    }
1763af6ab5fSopenharmony_ci    if (this.reservedPropertyNames.length > 0) {
1773af6ab5fSopenharmony_ci      resultStr += ObConfigResolver.KEEP_PROPERTY_NAME + '\n';
1783af6ab5fSopenharmony_ci      this.reservedPropertyNames.forEach((item) => {
1793af6ab5fSopenharmony_ci        resultStr += item + '\n';
1803af6ab5fSopenharmony_ci      });
1813af6ab5fSopenharmony_ci    }
1823af6ab5fSopenharmony_ci    return resultStr;
1833af6ab5fSopenharmony_ci  }
1843af6ab5fSopenharmony_ci}
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ciexport class ObConfigResolver {
1873af6ab5fSopenharmony_ci  sourceObConfig: any;
1883af6ab5fSopenharmony_ci  logger: any;
1893af6ab5fSopenharmony_ci  isHarCompiled: boolean | undefined;
1903af6ab5fSopenharmony_ci  isTerser: boolean;
1913af6ab5fSopenharmony_ci
1923af6ab5fSopenharmony_ci  constructor(projectConfig: any, logger: any, isTerser?: boolean) {
1933af6ab5fSopenharmony_ci    this.sourceObConfig = projectConfig.obfuscationOptions;
1943af6ab5fSopenharmony_ci    this.logger = logger;
1953af6ab5fSopenharmony_ci    this.isHarCompiled = projectConfig.compileHar;
1963af6ab5fSopenharmony_ci    this.isTerser = isTerser;
1973af6ab5fSopenharmony_ci  }
1983af6ab5fSopenharmony_ci
1993af6ab5fSopenharmony_ci  public resolveObfuscationConfigs(): MergedConfig {
2003af6ab5fSopenharmony_ci    let sourceObConfig = this.sourceObConfig;
2013af6ab5fSopenharmony_ci    if (!sourceObConfig) {
2023af6ab5fSopenharmony_ci      return new MergedConfig();
2033af6ab5fSopenharmony_ci    }
2043af6ab5fSopenharmony_ci    let enableObfuscation: boolean = sourceObConfig.selfConfig.ruleOptions.enable;
2053af6ab5fSopenharmony_ci
2063af6ab5fSopenharmony_ci    let selfConfig: MergedConfig = new MergedConfig();
2073af6ab5fSopenharmony_ci    if (enableObfuscation) {
2083af6ab5fSopenharmony_ci      this.getSelfConfigs(selfConfig);
2093af6ab5fSopenharmony_ci      enableObfuscation = !selfConfig.options.disableObfuscation;
2103af6ab5fSopenharmony_ci    } else {
2113af6ab5fSopenharmony_ci      selfConfig.options.disableObfuscation = true;
2123af6ab5fSopenharmony_ci    }
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_ci    let needConsumerConfigs: boolean =
2153af6ab5fSopenharmony_ci      this.isHarCompiled &&
2163af6ab5fSopenharmony_ci      sourceObConfig.selfConfig.consumerRules &&
2173af6ab5fSopenharmony_ci      sourceObConfig.selfConfig.consumerRules.length > 0;
2183af6ab5fSopenharmony_ci    let needDependencyConfigs: boolean = enableObfuscation || needConsumerConfigs;
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_ci    let dependencyConfigs: MergedConfig = new MergedConfig();
2213af6ab5fSopenharmony_ci    const dependencyMaxLength: number = Math.max(
2223af6ab5fSopenharmony_ci      sourceObConfig.dependencies.libraries.length,
2233af6ab5fSopenharmony_ci      sourceObConfig.dependencies.hars.length,
2243af6ab5fSopenharmony_ci    );
2253af6ab5fSopenharmony_ci    if (needDependencyConfigs && dependencyMaxLength > 0) {
2263af6ab5fSopenharmony_ci      dependencyConfigs = new MergedConfig();
2273af6ab5fSopenharmony_ci      this.getDependencyConfigs(sourceObConfig, dependencyConfigs);
2283af6ab5fSopenharmony_ci      enableObfuscation = enableObfuscation && !dependencyConfigs.options.disableObfuscation;
2293af6ab5fSopenharmony_ci    }
2303af6ab5fSopenharmony_ci    const mergedConfigs: MergedConfig = this.getMergedConfigs(selfConfig, dependencyConfigs);
2313af6ab5fSopenharmony_ci    UnobfuscationCollections.printKeptName = mergedConfigs.options.printKeptNames;
2323af6ab5fSopenharmony_ci    this.handleReservedArray(mergedConfigs);
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_ci    let needKeepSystemApi =
2353af6ab5fSopenharmony_ci      enableObfuscation &&
2363af6ab5fSopenharmony_ci      (mergedConfigs.options.enablePropertyObfuscation ||
2373af6ab5fSopenharmony_ci        (mergedConfigs.options.enableExportObfuscation && mergedConfigs.options.enableToplevelObfuscation));
2383af6ab5fSopenharmony_ci
2393af6ab5fSopenharmony_ci    if (needKeepSystemApi && sourceObConfig.obfuscationCacheDir) {
2403af6ab5fSopenharmony_ci      const systemApiCachePath: string = path.join(sourceObConfig.obfuscationCacheDir, 'systemApiCache.json');
2413af6ab5fSopenharmony_ci      if (isFileExist(systemApiCachePath)) {
2423af6ab5fSopenharmony_ci        this.getSystemApiConfigsByCache(systemApiCachePath);
2433af6ab5fSopenharmony_ci      } else {
2443af6ab5fSopenharmony_ci        performancePrinter?.iniPrinter?.startEvent('  Scan system api');
2453af6ab5fSopenharmony_ci        this.getSystemApiCache(mergedConfigs, systemApiCachePath);
2463af6ab5fSopenharmony_ci        performancePrinter?.iniPrinter?.endEvent('  Scan system api');
2473af6ab5fSopenharmony_ci      }
2483af6ab5fSopenharmony_ci    }
2493af6ab5fSopenharmony_ci
2503af6ab5fSopenharmony_ci    if (needConsumerConfigs) {
2513af6ab5fSopenharmony_ci      let selfConsumerConfig = new MergedConfig();
2523af6ab5fSopenharmony_ci      this.getSelfConsumerConfig(selfConsumerConfig);
2533af6ab5fSopenharmony_ci      this.genConsumerConfigFiles(sourceObConfig, selfConsumerConfig, dependencyConfigs);
2543af6ab5fSopenharmony_ci    }
2553af6ab5fSopenharmony_ci    return mergedConfigs;
2563af6ab5fSopenharmony_ci  }
2573af6ab5fSopenharmony_ci
2583af6ab5fSopenharmony_ci  private getSelfConfigs(selfConfigs: MergedConfig): void {
2593af6ab5fSopenharmony_ci    if (this.sourceObConfig.selfConfig.ruleOptions.rules) {
2603af6ab5fSopenharmony_ci      const configPaths: string[] = this.sourceObConfig.selfConfig.ruleOptions.rules;
2613af6ab5fSopenharmony_ci      for (const path of configPaths) {
2623af6ab5fSopenharmony_ci        this.getConfigByPath(path, selfConfigs);
2633af6ab5fSopenharmony_ci      }
2643af6ab5fSopenharmony_ci    }
2653af6ab5fSopenharmony_ci  }
2663af6ab5fSopenharmony_ci
2673af6ab5fSopenharmony_ci  public getSelfConfigsForTest(selfConfigs: MergedConfig): void {
2683af6ab5fSopenharmony_ci    return this.getSelfConfigs(selfConfigs);
2693af6ab5fSopenharmony_ci  }
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci  private getConfigByPath(path: string, configs: MergedConfig): void {
2723af6ab5fSopenharmony_ci    let fileContent = undefined;
2733af6ab5fSopenharmony_ci    try {
2743af6ab5fSopenharmony_ci      fileContent = fs.readFileSync(path, 'utf-8');
2753af6ab5fSopenharmony_ci    } catch (err) {
2763af6ab5fSopenharmony_ci      this.logger.error(`Failed to open ${path}. Error message: ${err}`);
2773af6ab5fSopenharmony_ci      throw err;
2783af6ab5fSopenharmony_ci    }
2793af6ab5fSopenharmony_ci    this.handleConfigContent(fileContent, configs, path);
2803af6ab5fSopenharmony_ci  }
2813af6ab5fSopenharmony_ci  
2823af6ab5fSopenharmony_ci  public getConfigByPathForTest(path: string, configs: MergedConfig): void {
2833af6ab5fSopenharmony_ci    return this.getConfigByPath(path, configs);
2843af6ab5fSopenharmony_ci  }
2853af6ab5fSopenharmony_ci
2863af6ab5fSopenharmony_ci  private handleReservedArray(mergedConfigs: MergedConfig): void {
2873af6ab5fSopenharmony_ci    if (mergedConfigs.options.enablePropertyObfuscation && mergedConfigs.reservedPropertyNames) {
2883af6ab5fSopenharmony_ci      const propertyReservedInfo: ReservedNameInfo = separateUniversalReservedItem(mergedConfigs.reservedPropertyNames);
2893af6ab5fSopenharmony_ci      mergedConfigs.universalReservedPropertyNames = propertyReservedInfo.universalReservedArray;
2903af6ab5fSopenharmony_ci      mergedConfigs.reservedPropertyNames = propertyReservedInfo.specificReservedArray;
2913af6ab5fSopenharmony_ci    }
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci    if (mergedConfigs.options.enableToplevelObfuscation && mergedConfigs.reservedGlobalNames) {
2943af6ab5fSopenharmony_ci      const globalReservedInfo: ReservedNameInfo = separateUniversalReservedItem(mergedConfigs.reservedGlobalNames);
2953af6ab5fSopenharmony_ci      mergedConfigs.universalReservedGlobalNames = globalReservedInfo.universalReservedArray;
2963af6ab5fSopenharmony_ci      mergedConfigs.reservedGlobalNames = globalReservedInfo.specificReservedArray;
2973af6ab5fSopenharmony_ci    }
2983af6ab5fSopenharmony_ci  }
2993af6ab5fSopenharmony_ci
3003af6ab5fSopenharmony_ci  public handleReservedArrayForTest(mergedConfigs: MergedConfig): void {
3013af6ab5fSopenharmony_ci    return this.handleReservedArray(mergedConfigs);
3023af6ab5fSopenharmony_ci  }
3033af6ab5fSopenharmony_ci
3043af6ab5fSopenharmony_ci  // obfuscation options
3053af6ab5fSopenharmony_ci  static readonly KEEP = '-keep';
3063af6ab5fSopenharmony_ci  static readonly KEEP_DTS = '-keep-dts';
3073af6ab5fSopenharmony_ci  static readonly KEEP_GLOBAL_NAME = '-keep-global-name';
3083af6ab5fSopenharmony_ci  static readonly KEEP_PROPERTY_NAME = '-keep-property-name';
3093af6ab5fSopenharmony_ci  static readonly KEEP_FILE_NAME = '-keep-file-name';
3103af6ab5fSopenharmony_ci  static readonly KEEP_COMMENTS = '-keep-comments';
3113af6ab5fSopenharmony_ci  static readonly DISABLE_OBFUSCATION = '-disable-obfuscation';
3123af6ab5fSopenharmony_ci  static readonly ENABLE_PROPERTY_OBFUSCATION = '-enable-property-obfuscation';
3133af6ab5fSopenharmony_ci  static readonly ENABLE_STRING_PROPERTY_OBFUSCATION = '-enable-string-property-obfuscation';
3143af6ab5fSopenharmony_ci  static readonly ENABLE_TOPLEVEL_OBFUSCATION = '-enable-toplevel-obfuscation';
3153af6ab5fSopenharmony_ci  static readonly ENABLE_FILENAME_OBFUSCATION = '-enable-filename-obfuscation';
3163af6ab5fSopenharmony_ci  static readonly ENABLE_EXPORT_OBFUSCATION = '-enable-export-obfuscation';
3173af6ab5fSopenharmony_ci  static readonly REMOVE_COMMENTS = '-remove-comments';
3183af6ab5fSopenharmony_ci  static readonly COMPACT = '-compact';
3193af6ab5fSopenharmony_ci  static readonly REMOVE_LOG = '-remove-log';
3203af6ab5fSopenharmony_ci  static readonly PRINT_NAMECACHE = '-print-namecache';
3213af6ab5fSopenharmony_ci  static readonly PRINT_KEPT_NAMES = '-print-kept-names';
3223af6ab5fSopenharmony_ci  static readonly APPLY_NAMECACHE = '-apply-namecache';
3233af6ab5fSopenharmony_ci
3243af6ab5fSopenharmony_ci  // renameFileName, printNameCache, applyNameCache, removeComments and keepComments won't be reserved in obfuscation.txt file.
3253af6ab5fSopenharmony_ci  static exportedSwitchMap: Map<string, string> = new Map([
3263af6ab5fSopenharmony_ci    ['disableObfuscation', ObConfigResolver.KEEP_DTS],
3273af6ab5fSopenharmony_ci    ['enablePropertyObfuscation', ObConfigResolver.ENABLE_PROPERTY_OBFUSCATION],
3283af6ab5fSopenharmony_ci    ['enableStringPropertyObfuscation', ObConfigResolver.ENABLE_STRING_PROPERTY_OBFUSCATION],
3293af6ab5fSopenharmony_ci    ['enableToplevelObfuscation', ObConfigResolver.ENABLE_TOPLEVEL_OBFUSCATION],
3303af6ab5fSopenharmony_ci    ['compact', ObConfigResolver.COMPACT],
3313af6ab5fSopenharmony_ci    ['removeLog', ObConfigResolver.REMOVE_LOG],
3323af6ab5fSopenharmony_ci  ]);
3333af6ab5fSopenharmony_ci
3343af6ab5fSopenharmony_ci  private getTokenType(token: string): OptionType {
3353af6ab5fSopenharmony_ci    switch (token) {
3363af6ab5fSopenharmony_ci      case ObConfigResolver.KEEP_DTS:
3373af6ab5fSopenharmony_ci        return OptionType.KEEP_DTS;
3383af6ab5fSopenharmony_ci      case ObConfigResolver.KEEP_GLOBAL_NAME:
3393af6ab5fSopenharmony_ci        return OptionType.KEEP_GLOBAL_NAME;
3403af6ab5fSopenharmony_ci      case ObConfigResolver.KEEP_PROPERTY_NAME:
3413af6ab5fSopenharmony_ci        return OptionType.KEEP_PROPERTY_NAME;
3423af6ab5fSopenharmony_ci      case ObConfigResolver.KEEP_FILE_NAME:
3433af6ab5fSopenharmony_ci        return OptionType.KEEP_FILE_NAME;
3443af6ab5fSopenharmony_ci      case ObConfigResolver.KEEP_COMMENTS:
3453af6ab5fSopenharmony_ci        return OptionType.KEEP_COMMENTS;
3463af6ab5fSopenharmony_ci      case ObConfigResolver.DISABLE_OBFUSCATION:
3473af6ab5fSopenharmony_ci        return OptionType.DISABLE_OBFUSCATION;
3483af6ab5fSopenharmony_ci      case ObConfigResolver.ENABLE_PROPERTY_OBFUSCATION:
3493af6ab5fSopenharmony_ci        return OptionType.ENABLE_PROPERTY_OBFUSCATION;
3503af6ab5fSopenharmony_ci      case ObConfigResolver.ENABLE_STRING_PROPERTY_OBFUSCATION:
3513af6ab5fSopenharmony_ci        return OptionType.ENABLE_STRING_PROPERTY_OBFUSCATION;
3523af6ab5fSopenharmony_ci      case ObConfigResolver.ENABLE_TOPLEVEL_OBFUSCATION:
3533af6ab5fSopenharmony_ci        return OptionType.ENABLE_TOPLEVEL_OBFUSCATION;
3543af6ab5fSopenharmony_ci      case ObConfigResolver.ENABLE_FILENAME_OBFUSCATION:
3553af6ab5fSopenharmony_ci        return OptionType.ENABLE_FILENAME_OBFUSCATION;
3563af6ab5fSopenharmony_ci      case ObConfigResolver.ENABLE_EXPORT_OBFUSCATION:
3573af6ab5fSopenharmony_ci        return OptionType.ENABLE_EXPORT_OBFUSCATION;
3583af6ab5fSopenharmony_ci      case ObConfigResolver.REMOVE_COMMENTS:
3593af6ab5fSopenharmony_ci        return OptionType.REMOVE_COMMENTS;
3603af6ab5fSopenharmony_ci      case ObConfigResolver.COMPACT:
3613af6ab5fSopenharmony_ci        return OptionType.COMPACT;
3623af6ab5fSopenharmony_ci      case ObConfigResolver.REMOVE_LOG:
3633af6ab5fSopenharmony_ci        return OptionType.REMOVE_LOG;
3643af6ab5fSopenharmony_ci      case ObConfigResolver.PRINT_NAMECACHE:
3653af6ab5fSopenharmony_ci        return OptionType.PRINT_NAMECACHE;
3663af6ab5fSopenharmony_ci      case ObConfigResolver.PRINT_KEPT_NAMES:
3673af6ab5fSopenharmony_ci        return OptionType.PRINT_KEPT_NAMES;
3683af6ab5fSopenharmony_ci      case ObConfigResolver.APPLY_NAMECACHE:
3693af6ab5fSopenharmony_ci        return OptionType.APPLY_NAMECACHE;
3703af6ab5fSopenharmony_ci      case ObConfigResolver.KEEP:
3713af6ab5fSopenharmony_ci        return OptionType.KEEP;
3723af6ab5fSopenharmony_ci      default:
3733af6ab5fSopenharmony_ci        return OptionType.NONE;
3743af6ab5fSopenharmony_ci    }
3753af6ab5fSopenharmony_ci  }
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_ci  public getTokenTypeForTest(token: string): OptionType {
3783af6ab5fSopenharmony_ci    return this.getTokenType(token);
3793af6ab5fSopenharmony_ci  }
3803af6ab5fSopenharmony_ci
3813af6ab5fSopenharmony_ci  private handleConfigContent(data: string, configs: MergedConfig, configPath: string): void {
3823af6ab5fSopenharmony_ci    data = this.removeComments(data);
3833af6ab5fSopenharmony_ci    const tokens = data.split(/[',', '\t', ' ', '\n', '\r\n']/).filter((item) => item !== '');
3843af6ab5fSopenharmony_ci    let type: OptionType = OptionType.NONE;
3853af6ab5fSopenharmony_ci    let tokenType: OptionType;
3863af6ab5fSopenharmony_ci    let dtsFilePaths: string[] = [];
3873af6ab5fSopenharmony_ci    let keepConfigs: string[] = [];
3883af6ab5fSopenharmony_ci    for (let i = 0; i < tokens.length; i++) {
3893af6ab5fSopenharmony_ci      const token = tokens[i];
3903af6ab5fSopenharmony_ci      tokenType = this.getTokenType(token);
3913af6ab5fSopenharmony_ci      // handle switches cases
3923af6ab5fSopenharmony_ci      switch (tokenType) {
3933af6ab5fSopenharmony_ci        case OptionType.DISABLE_OBFUSCATION: {
3943af6ab5fSopenharmony_ci          configs.options.disableObfuscation = true;
3953af6ab5fSopenharmony_ci          continue;
3963af6ab5fSopenharmony_ci        }
3973af6ab5fSopenharmony_ci        case OptionType.ENABLE_PROPERTY_OBFUSCATION: {
3983af6ab5fSopenharmony_ci          configs.options.enablePropertyObfuscation = true;
3993af6ab5fSopenharmony_ci          continue;
4003af6ab5fSopenharmony_ci        }
4013af6ab5fSopenharmony_ci        case OptionType.ENABLE_STRING_PROPERTY_OBFUSCATION: {
4023af6ab5fSopenharmony_ci          configs.options.enableStringPropertyObfuscation = true;
4033af6ab5fSopenharmony_ci          continue;
4043af6ab5fSopenharmony_ci        }
4053af6ab5fSopenharmony_ci        case OptionType.ENABLE_TOPLEVEL_OBFUSCATION: {
4063af6ab5fSopenharmony_ci          configs.options.enableToplevelObfuscation = true;
4073af6ab5fSopenharmony_ci          continue;
4083af6ab5fSopenharmony_ci        }
4093af6ab5fSopenharmony_ci        case OptionType.REMOVE_COMMENTS: {
4103af6ab5fSopenharmony_ci          configs.options.removeComments = true;
4113af6ab5fSopenharmony_ci          continue;
4123af6ab5fSopenharmony_ci        }
4133af6ab5fSopenharmony_ci        case OptionType.ENABLE_FILENAME_OBFUSCATION: {
4143af6ab5fSopenharmony_ci          configs.options.enableFileNameObfuscation = true;
4153af6ab5fSopenharmony_ci          continue;
4163af6ab5fSopenharmony_ci        }
4173af6ab5fSopenharmony_ci        case OptionType.ENABLE_EXPORT_OBFUSCATION: {
4183af6ab5fSopenharmony_ci          configs.options.enableExportObfuscation = true;
4193af6ab5fSopenharmony_ci          continue;
4203af6ab5fSopenharmony_ci        }
4213af6ab5fSopenharmony_ci        case OptionType.COMPACT: {
4223af6ab5fSopenharmony_ci          configs.options.compact = true;
4233af6ab5fSopenharmony_ci          continue;
4243af6ab5fSopenharmony_ci        }
4253af6ab5fSopenharmony_ci        case OptionType.REMOVE_LOG: {
4263af6ab5fSopenharmony_ci          configs.options.removeLog = true;
4273af6ab5fSopenharmony_ci          continue;
4283af6ab5fSopenharmony_ci        }
4293af6ab5fSopenharmony_ci        case OptionType.PRINT_KEPT_NAMES: {
4303af6ab5fSopenharmony_ci          configs.options.printKeptNames = true;
4313af6ab5fSopenharmony_ci          type = tokenType;
4323af6ab5fSopenharmony_ci          continue;
4333af6ab5fSopenharmony_ci        }
4343af6ab5fSopenharmony_ci        case OptionType.KEEP:
4353af6ab5fSopenharmony_ci        case OptionType.KEEP_DTS:
4363af6ab5fSopenharmony_ci        case OptionType.KEEP_GLOBAL_NAME:
4373af6ab5fSopenharmony_ci        case OptionType.KEEP_PROPERTY_NAME:
4383af6ab5fSopenharmony_ci        case OptionType.KEEP_FILE_NAME:
4393af6ab5fSopenharmony_ci        case OptionType.KEEP_COMMENTS:
4403af6ab5fSopenharmony_ci        case OptionType.PRINT_NAMECACHE:
4413af6ab5fSopenharmony_ci        case OptionType.APPLY_NAMECACHE:
4423af6ab5fSopenharmony_ci          type = tokenType;
4433af6ab5fSopenharmony_ci          continue;
4443af6ab5fSopenharmony_ci        default: {
4453af6ab5fSopenharmony_ci          // fall-through
4463af6ab5fSopenharmony_ci        }
4473af6ab5fSopenharmony_ci      }
4483af6ab5fSopenharmony_ci      // handle 'keep' options and 'namecache' options
4493af6ab5fSopenharmony_ci      switch (type) {
4503af6ab5fSopenharmony_ci        case OptionType.KEEP: {
4513af6ab5fSopenharmony_ci          keepConfigs.push(token);
4523af6ab5fSopenharmony_ci          continue;
4533af6ab5fSopenharmony_ci        }
4543af6ab5fSopenharmony_ci        case OptionType.KEEP_DTS: {
4553af6ab5fSopenharmony_ci          dtsFilePaths.push(token);
4563af6ab5fSopenharmony_ci          continue;
4573af6ab5fSopenharmony_ci        }
4583af6ab5fSopenharmony_ci        case OptionType.KEEP_GLOBAL_NAME: {
4593af6ab5fSopenharmony_ci          configs.reservedGlobalNames.push(token);
4603af6ab5fSopenharmony_ci          continue;
4613af6ab5fSopenharmony_ci        }
4623af6ab5fSopenharmony_ci        case OptionType.KEEP_PROPERTY_NAME: {
4633af6ab5fSopenharmony_ci          configs.reservedPropertyNames.push(token);
4643af6ab5fSopenharmony_ci          continue;
4653af6ab5fSopenharmony_ci        }
4663af6ab5fSopenharmony_ci        case OptionType.KEEP_FILE_NAME: {
4673af6ab5fSopenharmony_ci          configs.reservedFileNames.push(token);
4683af6ab5fSopenharmony_ci          continue;
4693af6ab5fSopenharmony_ci        }
4703af6ab5fSopenharmony_ci        case OptionType.KEEP_COMMENTS: {
4713af6ab5fSopenharmony_ci          configs.keepComments.push(token);
4723af6ab5fSopenharmony_ci          continue;
4733af6ab5fSopenharmony_ci        }
4743af6ab5fSopenharmony_ci        case OptionType.PRINT_NAMECACHE: {
4753af6ab5fSopenharmony_ci          configs.options.printNameCache = this.resolvePath(configPath, token);
4763af6ab5fSopenharmony_ci          type = OptionType.NONE;
4773af6ab5fSopenharmony_ci          continue;
4783af6ab5fSopenharmony_ci        }
4793af6ab5fSopenharmony_ci        case OptionType.PRINT_KEPT_NAMES: {
4803af6ab5fSopenharmony_ci          configs.options.printKeptNamesPath = this.resolvePath(configPath, token);
4813af6ab5fSopenharmony_ci          type = OptionType.NONE;
4823af6ab5fSopenharmony_ci          continue;
4833af6ab5fSopenharmony_ci        }
4843af6ab5fSopenharmony_ci        case OptionType.APPLY_NAMECACHE: {
4853af6ab5fSopenharmony_ci          const absNameCachePath: string = this.resolvePath(configPath, token);
4863af6ab5fSopenharmony_ci          this.determineNameCachePath(absNameCachePath, configPath);
4873af6ab5fSopenharmony_ci          configs.options.applyNameCache = absNameCachePath;
4883af6ab5fSopenharmony_ci          type = OptionType.NONE;
4893af6ab5fSopenharmony_ci          continue;
4903af6ab5fSopenharmony_ci        }
4913af6ab5fSopenharmony_ci        default:
4923af6ab5fSopenharmony_ci          continue;
4933af6ab5fSopenharmony_ci      }
4943af6ab5fSopenharmony_ci    }
4953af6ab5fSopenharmony_ci
4963af6ab5fSopenharmony_ci    this.resolveDts(dtsFilePaths, configs);
4973af6ab5fSopenharmony_ci    this.resolveKeepConfig(keepConfigs, configs, configPath);
4983af6ab5fSopenharmony_ci  }
4993af6ab5fSopenharmony_ci
5003af6ab5fSopenharmony_ci  public handleConfigContentForTest(data: string, configs: MergedConfig, configPath: string): void {
5013af6ab5fSopenharmony_ci    return this.handleConfigContent(data, configs, configPath);
5023af6ab5fSopenharmony_ci  } 
5033af6ab5fSopenharmony_ci  // get absolute path
5043af6ab5fSopenharmony_ci  private resolvePath(configPath: string, token: string): string {
5053af6ab5fSopenharmony_ci    if (path.isAbsolute(token)) {
5063af6ab5fSopenharmony_ci      return token;
5073af6ab5fSopenharmony_ci    }
5083af6ab5fSopenharmony_ci    const configDirectory = path.dirname(configPath);
5093af6ab5fSopenharmony_ci    return path.resolve(configDirectory, token);
5103af6ab5fSopenharmony_ci  }
5113af6ab5fSopenharmony_ci
5123af6ab5fSopenharmony_ci  public resolvePathForTest(configPath: string, token: string): string {
5133af6ab5fSopenharmony_ci    return this.resolvePath(configPath, token);
5143af6ab5fSopenharmony_ci  }
5153af6ab5fSopenharmony_ci
5163af6ab5fSopenharmony_ci  // get names in .d.ts files and add them into reserved list
5173af6ab5fSopenharmony_ci  private resolveDts(dtsFilePaths: string[], configs: MergedConfig): void {
5183af6ab5fSopenharmony_ci    ApiExtractor.mPropertySet.clear();
5193af6ab5fSopenharmony_ci    dtsFilePaths.forEach((token) => {
5203af6ab5fSopenharmony_ci      ApiExtractor.traverseApiFiles(token, ApiExtractor.ApiType.PROJECT);
5213af6ab5fSopenharmony_ci    });
5223af6ab5fSopenharmony_ci    configs.reservedNames = configs.reservedNames.concat([...ApiExtractor.mPropertySet]);
5233af6ab5fSopenharmony_ci    configs.reservedPropertyNames = configs.reservedPropertyNames.concat([...ApiExtractor.mPropertySet]);
5243af6ab5fSopenharmony_ci    configs.reservedGlobalNames = configs.reservedGlobalNames.concat([...ApiExtractor.mPropertySet]);
5253af6ab5fSopenharmony_ci    ApiExtractor.mPropertySet.clear();
5263af6ab5fSopenharmony_ci  }
5273af6ab5fSopenharmony_ci
5283af6ab5fSopenharmony_ci  public resolveKeepConfig(keepConfigs: string[], configs: MergedConfig, configPath: string): void {
5293af6ab5fSopenharmony_ci    for (let keepPath of keepConfigs) {
5303af6ab5fSopenharmony_ci      let tempAbsPath: string;
5313af6ab5fSopenharmony_ci      const isExclude: boolean = keepPath.startsWith('!');
5323af6ab5fSopenharmony_ci      // 1: remove '!'
5333af6ab5fSopenharmony_ci      tempAbsPath = FileUtils.getAbsPathBaseConfigPath(configPath, isExclude ? keepPath.substring(1) : keepPath);
5343af6ab5fSopenharmony_ci
5353af6ab5fSopenharmony_ci      // contains '*', '?'
5363af6ab5fSopenharmony_ci      if (containWildcards(tempAbsPath)) {
5373af6ab5fSopenharmony_ci        const regexPattern = wildcardTransformer(tempAbsPath, true);
5383af6ab5fSopenharmony_ci        const regexOperator = new RegExp(`^${regexPattern}$`);
5393af6ab5fSopenharmony_ci        if (isExclude) {
5403af6ab5fSopenharmony_ci          // start with '!'
5413af6ab5fSopenharmony_ci          configs.excludeUniversalPaths.push(regexOperator);
5423af6ab5fSopenharmony_ci        } else {
5433af6ab5fSopenharmony_ci          configs.keepUniversalPaths.push(regexOperator);
5443af6ab5fSopenharmony_ci        }
5453af6ab5fSopenharmony_ci        continue;
5463af6ab5fSopenharmony_ci      }
5473af6ab5fSopenharmony_ci
5483af6ab5fSopenharmony_ci      if (isExclude) {
5493af6ab5fSopenharmony_ci        // exclude specific path
5503af6ab5fSopenharmony_ci        configs.excludePathSet.add(tempAbsPath);
5513af6ab5fSopenharmony_ci        continue;
5523af6ab5fSopenharmony_ci      }
5533af6ab5fSopenharmony_ci
5543af6ab5fSopenharmony_ci      if (!fs.existsSync(tempAbsPath)) {
5553af6ab5fSopenharmony_ci        this.logger.warn(yellow + 'ArkTS: The path of obfuscation \'-keep\' configuration does not exist: ' + keepPath);
5563af6ab5fSopenharmony_ci        continue;
5573af6ab5fSopenharmony_ci      }
5583af6ab5fSopenharmony_ci      tempAbsPath = fs.realpathSync(tempAbsPath);
5593af6ab5fSopenharmony_ci      configs.keepSourceOfPaths.push(FileUtils.toUnixPath(tempAbsPath));
5603af6ab5fSopenharmony_ci    }
5613af6ab5fSopenharmony_ci  }
5623af6ab5fSopenharmony_ci
5633af6ab5fSopenharmony_ci  // the content from '#' to '\n' are comments
5643af6ab5fSopenharmony_ci  private removeComments(data: string): string {
5653af6ab5fSopenharmony_ci    const commentStart = '#';
5663af6ab5fSopenharmony_ci    const commentEnd = '\n';
5673af6ab5fSopenharmony_ci    let tmpStr = '';
5683af6ab5fSopenharmony_ci    let isInComments = false;
5693af6ab5fSopenharmony_ci    for (let i = 0; i < data.length; i++) {
5703af6ab5fSopenharmony_ci      if (isInComments) {
5713af6ab5fSopenharmony_ci        isInComments = data[i] !== commentEnd;
5723af6ab5fSopenharmony_ci      } else if (data[i] !== commentStart) {
5733af6ab5fSopenharmony_ci        tmpStr += data[i];
5743af6ab5fSopenharmony_ci      } else {
5753af6ab5fSopenharmony_ci        isInComments = true;
5763af6ab5fSopenharmony_ci      }
5773af6ab5fSopenharmony_ci    }
5783af6ab5fSopenharmony_ci    return tmpStr;
5793af6ab5fSopenharmony_ci  }
5803af6ab5fSopenharmony_ci
5813af6ab5fSopenharmony_ci  /**
5823af6ab5fSopenharmony_ci   * systemConfigs includes the API directorys.
5833af6ab5fSopenharmony_ci   * component directory and pre_define.js file path needs to be concatenated
5843af6ab5fSopenharmony_ci   * @param systemConfigs
5853af6ab5fSopenharmony_ci   */
5863af6ab5fSopenharmony_ci  private getSystemApiCache(systemConfigs: MergedConfig, systemApiCachePath: string): void {
5873af6ab5fSopenharmony_ci    ApiExtractor.mPropertySet.clear();
5883af6ab5fSopenharmony_ci    ApiExtractor.mSystemExportSet.clear();
5893af6ab5fSopenharmony_ci
5903af6ab5fSopenharmony_ci    interface ArkUIWhitelist {
5913af6ab5fSopenharmony_ci      ReservedPropertyNames: string[]
5923af6ab5fSopenharmony_ci    }
5933af6ab5fSopenharmony_ci    let arkUIWhitelist: ArkUIWhitelist = { ReservedPropertyNames: [] };
5943af6ab5fSopenharmony_ci    const sdkApis: string[] = sortAndDeduplicateStringArr(this.sourceObConfig.sdkApis);
5953af6ab5fSopenharmony_ci    for (let apiPath of sdkApis) {
5963af6ab5fSopenharmony_ci      this.getSdkApiCache(apiPath);
5973af6ab5fSopenharmony_ci      const UIPath: string = path.join(apiPath, '../build-tools/ets-loader/lib/pre_define.js');
5983af6ab5fSopenharmony_ci      if (fs.existsSync(UIPath)) {
5993af6ab5fSopenharmony_ci        this.getUIApiCache(UIPath);
6003af6ab5fSopenharmony_ci      }
6013af6ab5fSopenharmony_ci      const arkUIWhitelistPath: string = path.join(apiPath, '../build-tools/ets-loader/obfuscateWhiteList.json5');
6023af6ab5fSopenharmony_ci      if (fs.existsSync(arkUIWhitelistPath)) {
6033af6ab5fSopenharmony_ci        arkUIWhitelist = JSON5.parse(fs.readFileSync(arkUIWhitelistPath, 'utf-8'));
6043af6ab5fSopenharmony_ci      }
6053af6ab5fSopenharmony_ci    }
6063af6ab5fSopenharmony_ci    let systemApiContent: SystemApiContent = {};
6073af6ab5fSopenharmony_ci
6083af6ab5fSopenharmony_ci    if (systemConfigs.options.enablePropertyObfuscation) {
6093af6ab5fSopenharmony_ci      const savedNameAndPropertySet = new Set([...ApiExtractor.mPropertySet, ...arkUIWhitelist.ReservedPropertyNames]);
6103af6ab5fSopenharmony_ci      UnobfuscationCollections.reservedSdkApiForProp = savedNameAndPropertySet;
6113af6ab5fSopenharmony_ci      UnobfuscationCollections.reservedSdkApiForLocal = new Set(ApiExtractor.mPropertySet);
6123af6ab5fSopenharmony_ci      systemApiContent.ReservedPropertyNames = Array.from(savedNameAndPropertySet);
6133af6ab5fSopenharmony_ci      systemApiContent.ReservedLocalNames = Array.from(ApiExtractor.mPropertySet);
6143af6ab5fSopenharmony_ci    }
6153af6ab5fSopenharmony_ci    if (systemConfigs.options.enableToplevelObfuscation && systemConfigs.options.enableExportObfuscation) {
6163af6ab5fSopenharmony_ci      const savedExportNamesSet = new Set(ApiExtractor.mSystemExportSet);
6173af6ab5fSopenharmony_ci      UnobfuscationCollections.reservedSdkApiForGlobal = savedExportNamesSet;
6183af6ab5fSopenharmony_ci      systemApiContent.ReservedGlobalNames = Array.from(savedExportNamesSet);
6193af6ab5fSopenharmony_ci    }
6203af6ab5fSopenharmony_ci
6213af6ab5fSopenharmony_ci    if (!fs.existsSync(path.dirname(systemApiCachePath))) {
6223af6ab5fSopenharmony_ci      fs.mkdirSync(path.dirname(systemApiCachePath), { recursive: true });
6233af6ab5fSopenharmony_ci    }
6243af6ab5fSopenharmony_ci    fs.writeFileSync(systemApiCachePath, JSON.stringify(systemApiContent, null, 2));
6253af6ab5fSopenharmony_ci    ApiExtractor.mPropertySet.clear();
6263af6ab5fSopenharmony_ci    ApiExtractor.mSystemExportSet.clear();
6273af6ab5fSopenharmony_ci  }
6283af6ab5fSopenharmony_ci
6293af6ab5fSopenharmony_ci  public getSystemApiCacheForTest(systemConfigs: MergedConfig, systemApiCachePath: string): void {
6303af6ab5fSopenharmony_ci    return this.getSystemApiCache(systemConfigs, systemApiCachePath);
6313af6ab5fSopenharmony_ci  }
6323af6ab5fSopenharmony_ci
6333af6ab5fSopenharmony_ci  private getSdkApiCache(sdkApiPath: string): void {
6343af6ab5fSopenharmony_ci    ApiExtractor.traverseApiFiles(sdkApiPath, ApiExtractor.ApiType.API);
6353af6ab5fSopenharmony_ci    const componentPath: string = path.join(sdkApiPath, '../component');
6363af6ab5fSopenharmony_ci    if (fs.existsSync(componentPath)) {
6373af6ab5fSopenharmony_ci      ApiExtractor.traverseApiFiles(componentPath, ApiExtractor.ApiType.COMPONENT);
6383af6ab5fSopenharmony_ci    }
6393af6ab5fSopenharmony_ci  }
6403af6ab5fSopenharmony_ci
6413af6ab5fSopenharmony_ci  private getUIApiCache(uiApiPath: string): void {
6423af6ab5fSopenharmony_ci    ApiExtractor.extractStringsFromFile(uiApiPath);
6433af6ab5fSopenharmony_ci  }
6443af6ab5fSopenharmony_ci
6453af6ab5fSopenharmony_ci  private getDependencyConfigs(sourceObConfig: any, dependencyConfigs: MergedConfig): void {
6463af6ab5fSopenharmony_ci    for (const lib of sourceObConfig.dependencies.libraries || []) {
6473af6ab5fSopenharmony_ci      if (lib.consumerRules && lib.consumerRules.length > 0) {
6483af6ab5fSopenharmony_ci        for (const path of lib.consumerRules) {
6493af6ab5fSopenharmony_ci          const thisLibConfigs = new MergedConfig();
6503af6ab5fSopenharmony_ci          this.getConfigByPath(path, dependencyConfigs);
6513af6ab5fSopenharmony_ci          dependencyConfigs.merge(thisLibConfigs);
6523af6ab5fSopenharmony_ci        }
6533af6ab5fSopenharmony_ci      }
6543af6ab5fSopenharmony_ci    }
6553af6ab5fSopenharmony_ci
6563af6ab5fSopenharmony_ci    if (
6573af6ab5fSopenharmony_ci      sourceObConfig.dependencies &&
6583af6ab5fSopenharmony_ci      sourceObConfig.dependencies.hars &&
6593af6ab5fSopenharmony_ci      sourceObConfig.dependencies.hars.length > 0
6603af6ab5fSopenharmony_ci    ) {
6613af6ab5fSopenharmony_ci      for (const path of sourceObConfig.dependencies.hars) {
6623af6ab5fSopenharmony_ci        const thisHarConfigs = new MergedConfig();
6633af6ab5fSopenharmony_ci        this.getConfigByPath(path, dependencyConfigs);
6643af6ab5fSopenharmony_ci        dependencyConfigs.merge(thisHarConfigs);
6653af6ab5fSopenharmony_ci      }
6663af6ab5fSopenharmony_ci    }
6673af6ab5fSopenharmony_ci  }
6683af6ab5fSopenharmony_ci
6693af6ab5fSopenharmony_ci  public getDependencyConfigsForTest(sourceObConfig: any, dependencyConfigs: MergedConfig): void {
6703af6ab5fSopenharmony_ci    return this.getDependencyConfigs(sourceObConfig, dependencyConfigs);
6713af6ab5fSopenharmony_ci  }
6723af6ab5fSopenharmony_ci
6733af6ab5fSopenharmony_ci  private getSystemApiConfigsByCache(systemApiCachePath: string): void {
6743af6ab5fSopenharmony_ci    let systemApiContent: {
6753af6ab5fSopenharmony_ci      ReservedPropertyNames?: string[];
6763af6ab5fSopenharmony_ci      ReservedGlobalNames?: string[];
6773af6ab5fSopenharmony_ci      ReservedLocalNames?: string[];
6783af6ab5fSopenharmony_ci    } = JSON.parse(fs.readFileSync(systemApiCachePath, 'utf-8'));
6793af6ab5fSopenharmony_ci    if (systemApiContent.ReservedPropertyNames) {
6803af6ab5fSopenharmony_ci      UnobfuscationCollections.reservedSdkApiForProp = new Set(systemApiContent.ReservedPropertyNames);
6813af6ab5fSopenharmony_ci    }
6823af6ab5fSopenharmony_ci    if (systemApiContent.ReservedGlobalNames) {
6833af6ab5fSopenharmony_ci      UnobfuscationCollections.reservedSdkApiForGlobal = new Set(systemApiContent.ReservedGlobalNames);
6843af6ab5fSopenharmony_ci    }
6853af6ab5fSopenharmony_ci    if (systemApiContent.ReservedLocalNames) {
6863af6ab5fSopenharmony_ci      UnobfuscationCollections.reservedSdkApiForLocal = new Set(systemApiContent.ReservedLocalNames);
6873af6ab5fSopenharmony_ci    }
6883af6ab5fSopenharmony_ci  }
6893af6ab5fSopenharmony_ci
6903af6ab5fSopenharmony_ci  public getSystemApiConfigsByCacheForTest(systemApiCachePath: string): void {
6913af6ab5fSopenharmony_ci    return this.getSystemApiConfigsByCache(systemApiCachePath);
6923af6ab5fSopenharmony_ci  }
6933af6ab5fSopenharmony_ci
6943af6ab5fSopenharmony_ci  private getSelfConsumerConfig(selfConsumerConfig: MergedConfig): void {
6953af6ab5fSopenharmony_ci    for (const path of this.sourceObConfig.selfConfig.consumerRules) {
6963af6ab5fSopenharmony_ci      this.getConfigByPath(path, selfConsumerConfig);
6973af6ab5fSopenharmony_ci    }
6983af6ab5fSopenharmony_ci  }
6993af6ab5fSopenharmony_ci
7003af6ab5fSopenharmony_ci  public getSelfConsumerConfigForTest(selfConsumerConfig: MergedConfig): void {
7013af6ab5fSopenharmony_ci    return this.getSelfConsumerConfig(selfConsumerConfig);
7023af6ab5fSopenharmony_ci  }
7033af6ab5fSopenharmony_ci
7043af6ab5fSopenharmony_ci  private getMergedConfigs(selfConfigs: MergedConfig, dependencyConfigs: MergedConfig): MergedConfig {
7053af6ab5fSopenharmony_ci    if (dependencyConfigs) {
7063af6ab5fSopenharmony_ci      selfConfigs.merge(dependencyConfigs);
7073af6ab5fSopenharmony_ci    }
7083af6ab5fSopenharmony_ci    selfConfigs.sortAndDeduplicate();
7093af6ab5fSopenharmony_ci    return selfConfigs;
7103af6ab5fSopenharmony_ci  }
7113af6ab5fSopenharmony_ci
7123af6ab5fSopenharmony_ci  public getMergedConfigsForTest(selfConfigs: MergedConfig, dependencyConfigs: MergedConfig): MergedConfig {
7133af6ab5fSopenharmony_ci    return this.getMergedConfigs(selfConfigs, dependencyConfigs);
7143af6ab5fSopenharmony_ci  }
7153af6ab5fSopenharmony_ci
7163af6ab5fSopenharmony_ci  private genConsumerConfigFiles(
7173af6ab5fSopenharmony_ci    sourceObConfig: any,
7183af6ab5fSopenharmony_ci    selfConsumerConfig: MergedConfig,
7193af6ab5fSopenharmony_ci    dependencyConfigs: MergedConfig,
7203af6ab5fSopenharmony_ci  ): void {
7213af6ab5fSopenharmony_ci    selfConsumerConfig.merge(dependencyConfigs);
7223af6ab5fSopenharmony_ci    selfConsumerConfig.sortAndDeduplicate();
7233af6ab5fSopenharmony_ci    this.writeConsumerConfigFile(selfConsumerConfig, sourceObConfig.exportRulePath);
7243af6ab5fSopenharmony_ci  }
7253af6ab5fSopenharmony_ci
7263af6ab5fSopenharmony_ci  public genConsumerConfigFilesForTest(
7273af6ab5fSopenharmony_ci    sourceObConfig: any,
7283af6ab5fSopenharmony_ci    selfConsumerConfig: MergedConfig,
7293af6ab5fSopenharmony_ci    dependencyConfigs: MergedConfig,
7303af6ab5fSopenharmony_ci  ): void {
7313af6ab5fSopenharmony_ci    return this.genConsumerConfigFiles(sourceObConfig, selfConsumerConfig, dependencyConfigs);
7323af6ab5fSopenharmony_ci  }
7333af6ab5fSopenharmony_ci
7343af6ab5fSopenharmony_ci  public writeConsumerConfigFile(selfConsumerConfig: MergedConfig, outpath: string): void {
7353af6ab5fSopenharmony_ci    const configContent: string = selfConsumerConfig.serializeMergedConfig();
7363af6ab5fSopenharmony_ci    fs.writeFileSync(outpath, configContent);
7373af6ab5fSopenharmony_ci  }
7383af6ab5fSopenharmony_ci
7393af6ab5fSopenharmony_ci  private determineNameCachePath(nameCachePath: string, configPath: string): void {
7403af6ab5fSopenharmony_ci    if (!fs.existsSync(nameCachePath)) {
7413af6ab5fSopenharmony_ci      throw new Error(`The applied namecache file '${nameCachePath}' configured by '${configPath}' does not exist.`);
7423af6ab5fSopenharmony_ci    }
7433af6ab5fSopenharmony_ci  }
7443af6ab5fSopenharmony_ci}
7453af6ab5fSopenharmony_ci
7463af6ab5fSopenharmony_ci/**
7473af6ab5fSopenharmony_ci * Collect reserved file name configured in oh-package.json5 and module.json5.
7483af6ab5fSopenharmony_ci * @param ohPackagePath The 'main' and 'types' fileds in oh-package.json5 need to be reserved.
7493af6ab5fSopenharmony_ci * @param projectConfig Several paths or file contents in projectconfig need to be reserved.
7503af6ab5fSopenharmony_ci *   1: module.json's 'srcEntry' field
7513af6ab5fSopenharmony_ci *   2: projectPath: /library/src/main/ets
7523af6ab5fSopenharmony_ci *   3: cachePath: /library/build/default/cache/default/default@HarCompileArkTs/esmodules/release
7533af6ab5fSopenharmony_ci *      target reserved path: /library/build/default/cache/default/default@HarCompileArkTs/esmodules/release/src/main/ets
7543af6ab5fSopenharmony_ci *   4: aceModuleBuild/etsFortgz directory: /library/build/default/intermediates/loader_out/etsFortgz
7553af6ab5fSopenharmony_ci *      If compile the hsp module, the declaration file will be written to the 'aceModuleBuild/etsFortgz' directory.
7563af6ab5fSopenharmony_ci * @param modulePathMap packageName of local har package should be reserved as it is a fixed part of ohmUrl.
7573af6ab5fSopenharmony_ci *   example: modulePathMap: { packageName: path }
7583af6ab5fSopenharmony_ci * @returns reservedFileNames
7593af6ab5fSopenharmony_ci */
7603af6ab5fSopenharmony_ciexport function collectResevedFileNameInIDEConfig(
7613af6ab5fSopenharmony_ci  ohPackagePath: string,
7623af6ab5fSopenharmony_ci  projectConfig: any,
7633af6ab5fSopenharmony_ci  modulePathMap: Object | undefined,
7643af6ab5fSopenharmony_ci  entryArray: Array<string> | undefined,
7653af6ab5fSopenharmony_ci): string[] {
7663af6ab5fSopenharmony_ci  const reservedFileNames: string[] = [];
7673af6ab5fSopenharmony_ci  const moduleJsonPath: string = projectConfig.aceModuleJsonPath;
7683af6ab5fSopenharmony_ci  const projectPath: string = projectConfig.projectPath;
7693af6ab5fSopenharmony_ci  const cachePath: string = projectConfig.cachePath;
7703af6ab5fSopenharmony_ci
7713af6ab5fSopenharmony_ci  if (entryArray) {
7723af6ab5fSopenharmony_ci    entryArray.forEach((element) => {
7733af6ab5fSopenharmony_ci      FileUtils.collectPathReservedString(element, reservedFileNames);
7743af6ab5fSopenharmony_ci    });
7753af6ab5fSopenharmony_ci  }
7763af6ab5fSopenharmony_ci
7773af6ab5fSopenharmony_ci  if (modulePathMap) {
7783af6ab5fSopenharmony_ci    const modulePaths = Object.values(modulePathMap);
7793af6ab5fSopenharmony_ci    const moduleNames = Object.keys(modulePathMap);
7803af6ab5fSopenharmony_ci    modulePaths.forEach((val) => {
7813af6ab5fSopenharmony_ci      FileUtils.collectPathReservedString(val, reservedFileNames);
7823af6ab5fSopenharmony_ci    });
7833af6ab5fSopenharmony_ci    moduleNames.forEach((val) => {
7843af6ab5fSopenharmony_ci      FileUtils.collectPathReservedString(val, reservedFileNames);
7853af6ab5fSopenharmony_ci    });
7863af6ab5fSopenharmony_ci  }
7873af6ab5fSopenharmony_ci  if (fs.existsSync(ohPackagePath)) {
7883af6ab5fSopenharmony_ci    const ohPackageContent = JSON5.parse(fs.readFileSync(ohPackagePath, 'utf-8'));
7893af6ab5fSopenharmony_ci    ohPackageContent.main && FileUtils.collectPathReservedString(ohPackageContent.main, reservedFileNames);
7903af6ab5fSopenharmony_ci    ohPackageContent.types && FileUtils.collectPathReservedString(ohPackageContent.types, reservedFileNames);
7913af6ab5fSopenharmony_ci  }
7923af6ab5fSopenharmony_ci
7933af6ab5fSopenharmony_ci  if (fs.existsSync(moduleJsonPath)) {
7943af6ab5fSopenharmony_ci    const moduleJsonContent = JSON5.parse(fs.readFileSync(moduleJsonPath, 'utf-8'));
7953af6ab5fSopenharmony_ci    moduleJsonContent.module?.srcEntry &&
7963af6ab5fSopenharmony_ci      FileUtils.collectPathReservedString(moduleJsonContent.module?.srcEntry, reservedFileNames);
7973af6ab5fSopenharmony_ci  }
7983af6ab5fSopenharmony_ci
7993af6ab5fSopenharmony_ci  if (projectConfig.compileShared || projectConfig.byteCodeHar) {
8003af6ab5fSopenharmony_ci    FileUtils.collectPathReservedString(projectConfig.aceModuleBuild, reservedFileNames);
8013af6ab5fSopenharmony_ci    reservedFileNames.push('etsFortgz');
8023af6ab5fSopenharmony_ci  }
8033af6ab5fSopenharmony_ci
8043af6ab5fSopenharmony_ci  FileUtils.collectPathReservedString(projectPath, reservedFileNames);
8053af6ab5fSopenharmony_ci  FileUtils.collectPathReservedString(cachePath, reservedFileNames);
8063af6ab5fSopenharmony_ci  return reservedFileNames;
8073af6ab5fSopenharmony_ci}
8083af6ab5fSopenharmony_ci
8093af6ab5fSopenharmony_ciexport function readNameCache(nameCachePath: string, logger: any): void {
8103af6ab5fSopenharmony_ci  try {
8113af6ab5fSopenharmony_ci    const fileContent = fs.readFileSync(nameCachePath, 'utf-8');
8123af6ab5fSopenharmony_ci    const nameCache: {
8133af6ab5fSopenharmony_ci      compileSdkVersion?: string;
8143af6ab5fSopenharmony_ci      [key: string]: Object;
8153af6ab5fSopenharmony_ci      PropertyCache?: Object;
8163af6ab5fSopenharmony_ci      FileNameCache?: Object;
8173af6ab5fSopenharmony_ci    } = JSON.parse(fileContent);
8183af6ab5fSopenharmony_ci    if (nameCache.PropertyCache) {
8193af6ab5fSopenharmony_ci      PropCollections.historyMangledTable = getMapFromJson(nameCache.PropertyCache);
8203af6ab5fSopenharmony_ci    }
8213af6ab5fSopenharmony_ci    if (nameCache.FileNameCache) {
8223af6ab5fSopenharmony_ci      renameFileNameModule.historyFileNameMangledTable = getMapFromJson(nameCache.FileNameCache);
8233af6ab5fSopenharmony_ci    }
8243af6ab5fSopenharmony_ci
8253af6ab5fSopenharmony_ci    const { compileSdkVersion, PropertyCache, FileNameCache, ...rest } = nameCache;
8263af6ab5fSopenharmony_ci    Object.keys(rest).forEach((key) => {
8273af6ab5fSopenharmony_ci      nameCacheMap.set(key, rest[key]);
8283af6ab5fSopenharmony_ci    });
8293af6ab5fSopenharmony_ci  } catch (err) {
8303af6ab5fSopenharmony_ci    logger.error(`Failed to open ${nameCachePath}. Error message: ${err}`);
8313af6ab5fSopenharmony_ci  }
8323af6ab5fSopenharmony_ci}
8333af6ab5fSopenharmony_ci
8343af6ab5fSopenharmony_ci/**
8353af6ab5fSopenharmony_ci * collect the reserved or excluded paths containing wildcards
8363af6ab5fSopenharmony_ci */
8373af6ab5fSopenharmony_ciexport function handleUniversalPathInObf(mergedObConfig: MergedConfig, allSourceFilePaths: Set<string>): void {
8383af6ab5fSopenharmony_ci  if (
8393af6ab5fSopenharmony_ci    !mergedObConfig ||
8403af6ab5fSopenharmony_ci    (mergedObConfig.keepUniversalPaths.length === 0 && mergedObConfig.excludeUniversalPaths.length === 0)
8413af6ab5fSopenharmony_ci  ) {
8423af6ab5fSopenharmony_ci    return;
8433af6ab5fSopenharmony_ci  }
8443af6ab5fSopenharmony_ci  for (const realFilePath of allSourceFilePaths) {
8453af6ab5fSopenharmony_ci    let isReserved = false;
8463af6ab5fSopenharmony_ci    for (const universalPath of mergedObConfig.keepUniversalPaths) {
8473af6ab5fSopenharmony_ci      if (universalPath.test(realFilePath)) {
8483af6ab5fSopenharmony_ci        isReserved = true;
8493af6ab5fSopenharmony_ci        break;
8503af6ab5fSopenharmony_ci      }
8513af6ab5fSopenharmony_ci    }
8523af6ab5fSopenharmony_ci    for (const excludePath of mergedObConfig.excludeUniversalPaths) {
8533af6ab5fSopenharmony_ci      if (excludePath.test(realFilePath)) {
8543af6ab5fSopenharmony_ci        isReserved = false;
8553af6ab5fSopenharmony_ci        mergedObConfig.excludePathSet.add(realFilePath);
8563af6ab5fSopenharmony_ci        break;
8573af6ab5fSopenharmony_ci      }
8583af6ab5fSopenharmony_ci    }
8593af6ab5fSopenharmony_ci    if (isReserved) {
8603af6ab5fSopenharmony_ci      mergedObConfig.keepSourceOfPaths.push(realFilePath);
8613af6ab5fSopenharmony_ci    }
8623af6ab5fSopenharmony_ci  }
8633af6ab5fSopenharmony_ci}
8643af6ab5fSopenharmony_ci
8653af6ab5fSopenharmony_ciexport function getArkguardNameCache(
8663af6ab5fSopenharmony_ci  enablePropertyObfuscation: boolean,
8673af6ab5fSopenharmony_ci  enableFileNameObfuscation: boolean,
8683af6ab5fSopenharmony_ci  enableExportObfuscation: boolean,
8693af6ab5fSopenharmony_ci  sdkVersion: string,
8703af6ab5fSopenharmony_ci  entryPackageInfo: string,
8713af6ab5fSopenharmony_ci): string {
8723af6ab5fSopenharmony_ci  let writeContent: string = '';
8733af6ab5fSopenharmony_ci  let nameCacheCollection: {
8743af6ab5fSopenharmony_ci    compileSdkVersion?: string;
8753af6ab5fSopenharmony_ci    PropertyCache?: Object;
8763af6ab5fSopenharmony_ci    FileNameCache?: Object;
8773af6ab5fSopenharmony_ci    entryPackageInfo?: string;
8783af6ab5fSopenharmony_ci  } = Object.fromEntries(nameCacheMap.entries());
8793af6ab5fSopenharmony_ci  nameCacheCollection.compileSdkVersion = sdkVersion;
8803af6ab5fSopenharmony_ci  nameCacheCollection.entryPackageInfo = entryPackageInfo;
8813af6ab5fSopenharmony_ci
8823af6ab5fSopenharmony_ci  if (enablePropertyObfuscation || enableExportObfuscation) {
8833af6ab5fSopenharmony_ci    const mergedPropertyNameCache: Map<string, string> = new Map();
8843af6ab5fSopenharmony_ci    fillNameCache(PropCollections.historyMangledTable, mergedPropertyNameCache);
8853af6ab5fSopenharmony_ci    fillNameCache(PropCollections.globalMangledTable, mergedPropertyNameCache);
8863af6ab5fSopenharmony_ci    nameCacheCollection.PropertyCache = Object.fromEntries(mergedPropertyNameCache);
8873af6ab5fSopenharmony_ci  }
8883af6ab5fSopenharmony_ci
8893af6ab5fSopenharmony_ci  if (enableFileNameObfuscation) {
8903af6ab5fSopenharmony_ci    const mergedFileNameCache: Map<string, string> = new Map();
8913af6ab5fSopenharmony_ci    fillNameCache(renameFileNameModule.historyFileNameMangledTable, mergedFileNameCache);
8923af6ab5fSopenharmony_ci    fillNameCache(renameFileNameModule.globalFileNameMangledTable, mergedFileNameCache);
8933af6ab5fSopenharmony_ci    nameCacheCollection.FileNameCache = Object.fromEntries(mergedFileNameCache);
8943af6ab5fSopenharmony_ci  }
8953af6ab5fSopenharmony_ci
8963af6ab5fSopenharmony_ci  writeContent += JSON.stringify(nameCacheCollection, null, 2);
8973af6ab5fSopenharmony_ci  return writeContent;
8983af6ab5fSopenharmony_ci}
8993af6ab5fSopenharmony_ci
9003af6ab5fSopenharmony_ci// export fillNameCache function
9013af6ab5fSopenharmony_ciexport function fillNameCache(table: Map<string, string>, nameCache: Map<string, string>): void {
9023af6ab5fSopenharmony_ci  if (table) {
9033af6ab5fSopenharmony_ci    for (const [key, value] of table.entries()) {
9043af6ab5fSopenharmony_ci      nameCache.set(key, value);
9053af6ab5fSopenharmony_ci    }
9063af6ab5fSopenharmony_ci  }
9073af6ab5fSopenharmony_ci  return;
9083af6ab5fSopenharmony_ci}
9093af6ab5fSopenharmony_ci
9103af6ab5fSopenharmony_ciexport function writeObfuscationNameCache(
9113af6ab5fSopenharmony_ci  projectConfig: any,
9123af6ab5fSopenharmony_ci  entryPackageInfo: string,
9133af6ab5fSopenharmony_ci  obfuscationCacheDir?: string,
9143af6ab5fSopenharmony_ci  printNameCache?: string,
9153af6ab5fSopenharmony_ci): void {
9163af6ab5fSopenharmony_ci  if (!projectConfig.arkObfuscator) {
9173af6ab5fSopenharmony_ci    return;
9183af6ab5fSopenharmony_ci  }
9193af6ab5fSopenharmony_ci  let options = projectConfig.obfuscationMergedObConfig.options;
9203af6ab5fSopenharmony_ci  let writeContent = getArkguardNameCache(
9213af6ab5fSopenharmony_ci    options.enablePropertyObfuscation,
9223af6ab5fSopenharmony_ci    options.enableFileNameObfuscation,
9233af6ab5fSopenharmony_ci    options.enableExportObfuscation,
9243af6ab5fSopenharmony_ci    projectConfig.etsLoaderVersion,
9253af6ab5fSopenharmony_ci    entryPackageInfo,
9263af6ab5fSopenharmony_ci  );
9273af6ab5fSopenharmony_ci  if (obfuscationCacheDir && obfuscationCacheDir.length > 0) {
9283af6ab5fSopenharmony_ci    const defaultNameCachePath: string = path.join(obfuscationCacheDir, 'nameCache.json');
9293af6ab5fSopenharmony_ci    if (!fs.existsSync(path.dirname(defaultNameCachePath))) {
9303af6ab5fSopenharmony_ci      fs.mkdirSync(path.dirname(defaultNameCachePath), { recursive: true });
9313af6ab5fSopenharmony_ci    }
9323af6ab5fSopenharmony_ci    fs.writeFileSync(defaultNameCachePath, writeContent);
9333af6ab5fSopenharmony_ci  }
9343af6ab5fSopenharmony_ci  if (printNameCache && printNameCache.length > 0) {
9353af6ab5fSopenharmony_ci    fs.writeFileSync(printNameCache, writeContent);
9363af6ab5fSopenharmony_ci  }
9373af6ab5fSopenharmony_ci}
9383af6ab5fSopenharmony_ci
9393af6ab5fSopenharmony_ci// Print unobfuscation names, reasons and whitelist, if -print-kept-names is enabled.
9403af6ab5fSopenharmony_ciexport function writeUnobfuscationContent(projectConfig: any): void {
9413af6ab5fSopenharmony_ci  let obfuscationOptions = projectConfig.obfuscationMergedObConfig.options;
9423af6ab5fSopenharmony_ci  let unobfuscationOptions = projectConfig.arkObfuscator.mCustomProfiles.mUnobfuscationOption;
9433af6ab5fSopenharmony_ci  let nameOptions = projectConfig.arkObfuscator.mCustomProfiles.mNameObfuscation;
9443af6ab5fSopenharmony_ci  if (!unobfuscationOptions.mPrintKeptNames) {
9453af6ab5fSopenharmony_ci    return;
9463af6ab5fSopenharmony_ci  }
9473af6ab5fSopenharmony_ci
9483af6ab5fSopenharmony_ci  let configPath = unobfuscationOptions.mPrintPath;
9493af6ab5fSopenharmony_ci  let printDir = projectConfig.obfuscationOptions.obfuscationCacheDir;
9503af6ab5fSopenharmony_ci  let printUnobfPath = path.join(printDir, 'keptNames.json');
9513af6ab5fSopenharmony_ci  printUnobfuscationReasons(configPath, printUnobfPath);
9523af6ab5fSopenharmony_ci  let printWhitelistPath = path.join(printDir, 'whitelist.json');
9533af6ab5fSopenharmony_ci  printWhitelist(obfuscationOptions, nameOptions, printWhitelistPath);
9543af6ab5fSopenharmony_ci}
9553af6ab5fSopenharmony_ci
9563af6ab5fSopenharmony_ci// Merge similar whitelists and output according to whether the corresponding options are enabled.
9573af6ab5fSopenharmony_ciexport function printWhitelist(obfuscationOptions: ObOptions, nameOptions: INameObfuscationOption, defaultPath: string): void {
9583af6ab5fSopenharmony_ci  const enableToplevel = obfuscationOptions.enableToplevelObfuscation;
9593af6ab5fSopenharmony_ci  const enableProperty = obfuscationOptions.enablePropertyObfuscation;
9603af6ab5fSopenharmony_ci  const enableStringProp = obfuscationOptions.enableStringPropertyObfuscation;
9613af6ab5fSopenharmony_ci  const enableExport = obfuscationOptions.enableExportObfuscation;
9623af6ab5fSopenharmony_ci  const reservedConfToplevelArrary = nameOptions.mReservedToplevelNames ?? [];
9633af6ab5fSopenharmony_ci  const reservedConfPropertyArray = nameOptions.mReservedProperties ?? [];
9643af6ab5fSopenharmony_ci  let whitelistObj = {
9653af6ab5fSopenharmony_ci    lang: [],
9663af6ab5fSopenharmony_ci    conf: [],
9673af6ab5fSopenharmony_ci    struct: [],
9683af6ab5fSopenharmony_ci    exported: [],
9693af6ab5fSopenharmony_ci    strProp: [],
9703af6ab5fSopenharmony_ci    enum: []
9713af6ab5fSopenharmony_ci  };
9723af6ab5fSopenharmony_ci
9733af6ab5fSopenharmony_ci  let languareSet: Set<string>;
9743af6ab5fSopenharmony_ci  if (enableProperty) {
9753af6ab5fSopenharmony_ci    languareSet = mergeSet(UnobfuscationCollections.reservedLangForProperty, LocalVariableCollections.reservedLangForLocal);
9763af6ab5fSopenharmony_ci  } else {
9773af6ab5fSopenharmony_ci    languareSet = LocalVariableCollections.reservedLangForLocal;
9783af6ab5fSopenharmony_ci  }
9793af6ab5fSopenharmony_ci  whitelistObj.lang = convertSetToArray(languareSet);
9803af6ab5fSopenharmony_ci
9813af6ab5fSopenharmony_ci  let structSet: Set<string>;
9823af6ab5fSopenharmony_ci  if (enableProperty) {
9833af6ab5fSopenharmony_ci    structSet = mergeSet(UnobfuscationCollections.reservedStruct, LocalVariableCollections.reservedStruct);
9843af6ab5fSopenharmony_ci  } else {
9853af6ab5fSopenharmony_ci    structSet = LocalVariableCollections.reservedStruct;
9863af6ab5fSopenharmony_ci  }
9873af6ab5fSopenharmony_ci  whitelistObj.struct = convertSetToArray(structSet);
9883af6ab5fSopenharmony_ci
9893af6ab5fSopenharmony_ci  let exportedSet: Set<string>;
9903af6ab5fSopenharmony_ci  if (enableProperty) {
9913af6ab5fSopenharmony_ci    exportedSet = UnobfuscationCollections.reservedExportNameAndProp;
9923af6ab5fSopenharmony_ci  } else if (enableExport) {
9933af6ab5fSopenharmony_ci    exportedSet = UnobfuscationCollections.reservedExportName;
9943af6ab5fSopenharmony_ci  }
9953af6ab5fSopenharmony_ci  whitelistObj.exported = convertSetToArray(exportedSet);
9963af6ab5fSopenharmony_ci
9973af6ab5fSopenharmony_ci  let stringSet: Set<string>;
9983af6ab5fSopenharmony_ci  if (enableProperty && !enableStringProp) {
9993af6ab5fSopenharmony_ci    stringSet = UnobfuscationCollections.reservedStrProp;
10003af6ab5fSopenharmony_ci  }
10013af6ab5fSopenharmony_ci  whitelistObj.strProp = convertSetToArray(stringSet);
10023af6ab5fSopenharmony_ci
10033af6ab5fSopenharmony_ci  whitelistObj.conf = convertSetToArray(LocalVariableCollections.reservedConfig);
10043af6ab5fSopenharmony_ci  const hasPropertyConfig = enableProperty && reservedConfPropertyArray?.length > 0;
10053af6ab5fSopenharmony_ci  const hasTopLevelConfig = enableToplevel && reservedConfToplevelArrary?.length > 0;
10063af6ab5fSopenharmony_ci  if (hasPropertyConfig) {
10073af6ab5fSopenharmony_ci    whitelistObj.conf.push(...reservedConfPropertyArray);
10083af6ab5fSopenharmony_ci    handleUniversalReservedList(nameOptions.mUniversalReservedProperties, whitelistObj.conf);
10093af6ab5fSopenharmony_ci  }
10103af6ab5fSopenharmony_ci  if (hasTopLevelConfig) {
10113af6ab5fSopenharmony_ci    whitelistObj.conf.push(...reservedConfToplevelArrary);
10123af6ab5fSopenharmony_ci    handleUniversalReservedList(nameOptions.mUniversalReservedToplevelNames, whitelistObj.conf);
10133af6ab5fSopenharmony_ci  }
10143af6ab5fSopenharmony_ci
10153af6ab5fSopenharmony_ci  let enumSet: Set<string>;
10163af6ab5fSopenharmony_ci  if (enableProperty) {
10173af6ab5fSopenharmony_ci    enumSet = UnobfuscationCollections.reservedEnum;
10183af6ab5fSopenharmony_ci  } 
10193af6ab5fSopenharmony_ci  whitelistObj.enum = convertSetToArray(enumSet);
10203af6ab5fSopenharmony_ci
10213af6ab5fSopenharmony_ci  let whitelistContent = JSON.stringify(whitelistObj, null, 2); // 2: indentation
10223af6ab5fSopenharmony_ci  if (!fs.existsSync(path.dirname(defaultPath))) {
10233af6ab5fSopenharmony_ci    fs.mkdirSync(path.dirname(defaultPath), { recursive: true });
10243af6ab5fSopenharmony_ci  }
10253af6ab5fSopenharmony_ci  fs.writeFileSync(defaultPath, whitelistContent);
10263af6ab5fSopenharmony_ci}
10273af6ab5fSopenharmony_ci
10283af6ab5fSopenharmony_cifunction handleUniversalReservedList(universalList: RegExp[] | undefined, configArray: string[]): void {
10293af6ab5fSopenharmony_ci  if (universalList?.length > 0) {
10303af6ab5fSopenharmony_ci    universalList.forEach((value) => {
10313af6ab5fSopenharmony_ci      const originalString = UnobfuscationCollections.reservedWildcardMap.get(value);
10323af6ab5fSopenharmony_ci      if (originalString) {
10333af6ab5fSopenharmony_ci        configArray.push(originalString);
10343af6ab5fSopenharmony_ci      }
10353af6ab5fSopenharmony_ci    });
10363af6ab5fSopenharmony_ci  }
10373af6ab5fSopenharmony_ci}
10383af6ab5fSopenharmony_ci
10393af6ab5fSopenharmony_ci// Merge KeptReasons and KeptNames and output
10403af6ab5fSopenharmony_ciexport function printUnobfuscationReasons(configPath: string, defaultPath: string): void {
10413af6ab5fSopenharmony_ci  let property: Record<string, string[]> = {};
10423af6ab5fSopenharmony_ci  let unobfuscationObj = { keptReasons: {}, keptNames: { property } };
10433af6ab5fSopenharmony_ci  type WhitelistObject = {
10443af6ab5fSopenharmony_ci    [key in WhitelistType]: string;
10453af6ab5fSopenharmony_ci  };
10463af6ab5fSopenharmony_ci  let keptReasons: WhitelistObject = {
10473af6ab5fSopenharmony_ci    sdk: 'same as the system api names',
10483af6ab5fSopenharmony_ci    lang: 'same as the language keywords',
10493af6ab5fSopenharmony_ci    conf: 'same as the user-configured kept name',
10503af6ab5fSopenharmony_ci    struct: 'same as the ArkUI struct property',
10513af6ab5fSopenharmony_ci    strProp: 'same as the string property',
10523af6ab5fSopenharmony_ci    exported: 'same as the exported names and properties',
10533af6ab5fSopenharmony_ci    enum: 'same as the members in the enum'
10543af6ab5fSopenharmony_ci  };
10553af6ab5fSopenharmony_ci  unobfuscationObj.keptReasons = keptReasons;
10563af6ab5fSopenharmony_ci
10573af6ab5fSopenharmony_ci  if (!historyUnobfuscatedPropMap) {
10583af6ab5fSopenharmony_ci    // Full build
10593af6ab5fSopenharmony_ci    UnobfuscationCollections.unobfuscatedPropMap.forEach((value: Set<string>, key: string) => {
10603af6ab5fSopenharmony_ci      let array: string[] = Array.from(value);
10613af6ab5fSopenharmony_ci      unobfuscationObj.keptNames.property[key] = array;
10623af6ab5fSopenharmony_ci    });
10633af6ab5fSopenharmony_ci  } else {
10643af6ab5fSopenharmony_ci    // Incremental build
10653af6ab5fSopenharmony_ci    UnobfuscationCollections.unobfuscatedPropMap.forEach((value: Set<string>, key: string) => {
10663af6ab5fSopenharmony_ci      let array: string[] = Array.from(value);
10673af6ab5fSopenharmony_ci      historyUnobfuscatedPropMap.set(key, array);
10683af6ab5fSopenharmony_ci    });
10693af6ab5fSopenharmony_ci    historyUnobfuscatedPropMap.forEach((value: string[], key: string) => {
10703af6ab5fSopenharmony_ci      unobfuscationObj.keptNames.property[key] = value;
10713af6ab5fSopenharmony_ci    });
10723af6ab5fSopenharmony_ci  }
10733af6ab5fSopenharmony_ci  Object.assign(unobfuscationObj.keptNames, unobfuscationNamesObj);
10743af6ab5fSopenharmony_ci  let unobfuscationContent = JSON.stringify(unobfuscationObj, null, 2);
10753af6ab5fSopenharmony_ci  if (!fs.existsSync(path.dirname(defaultPath))) {
10763af6ab5fSopenharmony_ci    fs.mkdirSync(path.dirname(defaultPath), { recursive: true });
10773af6ab5fSopenharmony_ci  }
10783af6ab5fSopenharmony_ci  fs.writeFileSync(defaultPath, unobfuscationContent);
10793af6ab5fSopenharmony_ci  
10803af6ab5fSopenharmony_ci  if (!fs.existsSync(path.dirname(configPath))) {
10813af6ab5fSopenharmony_ci    fs.mkdirSync(path.dirname(configPath), { recursive: true });
10823af6ab5fSopenharmony_ci  }
10833af6ab5fSopenharmony_ci  if (configPath) {
10843af6ab5fSopenharmony_ci    fs.copyFileSync(defaultPath, configPath);
10853af6ab5fSopenharmony_ci  }
10863af6ab5fSopenharmony_ci}
10873af6ab5fSopenharmony_ci
10883af6ab5fSopenharmony_ci
10893af6ab5fSopenharmony_ciexport function generateConsumerObConfigFile(obfuscationOptions: any, logger: any): void {
10903af6ab5fSopenharmony_ci  const projectConfig = { obfuscationOptions, compileHar: true };
10913af6ab5fSopenharmony_ci  const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, logger);
10923af6ab5fSopenharmony_ci  obConfig.resolveObfuscationConfigs();
10933af6ab5fSopenharmony_ci}
10943af6ab5fSopenharmony_ci
10953af6ab5fSopenharmony_ciexport function mangleFilePath(originalPath: string): string {
10963af6ab5fSopenharmony_ci  const mangledFilePath = renameFileNameModule.getMangleCompletePath(originalPath);
10973af6ab5fSopenharmony_ci  return mangledFilePath;
10983af6ab5fSopenharmony_ci}
10993af6ab5fSopenharmony_ci
11003af6ab5fSopenharmony_ciexport function enableObfuscatedFilePathConfig(isPackageModules: boolean, projectConfig: any): boolean {
11013af6ab5fSopenharmony_ci  const isDebugMode = isDebug(projectConfig);
11023af6ab5fSopenharmony_ci  const hasObfuscationConfig = projectConfig.obfuscationMergedObConfig;
11033af6ab5fSopenharmony_ci  if (isDebugMode || !hasObfuscationConfig) {
11043af6ab5fSopenharmony_ci    return false;
11053af6ab5fSopenharmony_ci  }
11063af6ab5fSopenharmony_ci  const disableObfuscation = hasObfuscationConfig.options.disableObfuscation;
11073af6ab5fSopenharmony_ci  const enableFileNameObfuscation = hasObfuscationConfig.options.enableFileNameObfuscation;
11083af6ab5fSopenharmony_ci  if (disableObfuscation || !enableFileNameObfuscation) {
11093af6ab5fSopenharmony_ci    return false;
11103af6ab5fSopenharmony_ci  }
11113af6ab5fSopenharmony_ci  return true;
11123af6ab5fSopenharmony_ci}
11133af6ab5fSopenharmony_ci
11143af6ab5fSopenharmony_ciexport function handleObfuscatedFilePath(filePath: string, isPackageModules: boolean, projectConfig: Object): string {
11153af6ab5fSopenharmony_ci  if (!enableObfuscatedFilePathConfig(isPackageModules, projectConfig)) {
11163af6ab5fSopenharmony_ci    return filePath;
11173af6ab5fSopenharmony_ci  }
11183af6ab5fSopenharmony_ci  // Do not obfuscate the file path in dir oh_modules.
11193af6ab5fSopenharmony_ci  if (!isPackageModules) {
11203af6ab5fSopenharmony_ci    return mangleFilePath(filePath);
11213af6ab5fSopenharmony_ci  }
11223af6ab5fSopenharmony_ci  // When open the config 'enableFileNameObfuscation', keeping all paths in unix format.
11233af6ab5fSopenharmony_ci  return FileUtils.toUnixPath(filePath);
11243af6ab5fSopenharmony_ci}
11253af6ab5fSopenharmony_ci
11263af6ab5fSopenharmony_ciexport function enableObfuscateFileName(isPackageModules: boolean, projectConfig: Object): boolean {
11273af6ab5fSopenharmony_ci  if (!enableObfuscatedFilePathConfig(isPackageModules, projectConfig)) {
11283af6ab5fSopenharmony_ci    return false;
11293af6ab5fSopenharmony_ci  }
11303af6ab5fSopenharmony_ci
11313af6ab5fSopenharmony_ci  // Do not obfuscate the file path in dir oh_modules.
11323af6ab5fSopenharmony_ci  if (!isPackageModules) {
11333af6ab5fSopenharmony_ci    return true;
11343af6ab5fSopenharmony_ci  }
11353af6ab5fSopenharmony_ci  // When open the config 'enableFileNameObfuscation', keeping all paths in unix format.
11363af6ab5fSopenharmony_ci  return false;
11373af6ab5fSopenharmony_ci}
11383af6ab5fSopenharmony_ci
11393af6ab5fSopenharmony_ci/**
11403af6ab5fSopenharmony_ci * Get the relative path relative to the project based on the file's associated project
11413af6ab5fSopenharmony_ci */
11423af6ab5fSopenharmony_ciexport function getRelativeSourcePath(
11433af6ab5fSopenharmony_ci  filePath: string,
11443af6ab5fSopenharmony_ci  projectRootPath: string,
11453af6ab5fSopenharmony_ci  belongProjectPath: string | undefined,
11463af6ab5fSopenharmony_ci): string {
11473af6ab5fSopenharmony_ci  filePath = FileUtils.toUnixPath(filePath);
11483af6ab5fSopenharmony_ci
11493af6ab5fSopenharmony_ci  if (projectRootPath) {
11503af6ab5fSopenharmony_ci    projectRootPath = FileUtils.toUnixPath(projectRootPath);
11513af6ab5fSopenharmony_ci  }
11523af6ab5fSopenharmony_ci
11533af6ab5fSopenharmony_ci  if (belongProjectPath) {
11543af6ab5fSopenharmony_ci    belongProjectPath = FileUtils.toUnixPath(belongProjectPath);
11553af6ab5fSopenharmony_ci  }
11563af6ab5fSopenharmony_ci
11573af6ab5fSopenharmony_ci  let relativeFilePath: string = filePath;
11583af6ab5fSopenharmony_ci  if (projectRootPath && filePath.startsWith(projectRootPath)) {
11593af6ab5fSopenharmony_ci    relativeFilePath = filePath.replace(projectRootPath + '/', '');
11603af6ab5fSopenharmony_ci  } else if (belongProjectPath) {
11613af6ab5fSopenharmony_ci    relativeFilePath = filePath.replace(belongProjectPath + '/', '');
11623af6ab5fSopenharmony_ci  }
11633af6ab5fSopenharmony_ci
11643af6ab5fSopenharmony_ci  return relativeFilePath;
11653af6ab5fSopenharmony_ci}
1166