* Copyright (c) 2025-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
createPrinter,
createTextWriter,
transform,
createObfTextSingleLineWriter,
} from 'typescript';
import type {
CompilerOptions,
EmitTextWriter,
Node,
Printer,
PrinterOptions,
RawSourceMap,
SourceFile,
SourceMapGenerator,
TransformationResult,
TransformerFactory,
} from 'typescript';
import path from 'path';
import {
AtIntentCollections,
AtKeepCollections,
BytecodeObfuscationCollections,
LocalVariableCollections,
PropCollections
} from './utils/CommonCollections';
import type { IOptions } from './configs/IOptions';
import { FileUtils } from './utils/FileUtils';
import { TransformerManager } from './transformers/TransformerManager';
import { getSourceMapGenerator } from './utils/SourceMapUtil';
import {
decodeSourcemap,
ExistingDecodedSourceMap,
Source,
SourceMapLink,
SourceMapSegmentObj,
mergeSourceMap
} from './utils/SourceMapMergingUtil';
import {
deleteLineInfoForNameString,
getMapFromJson,
IDENTIFIER_CACHE,
MEM_METHOD_CACHE
} from './utils/NameCacheUtil';
import { needReadApiInfo, readProjectPropertiesByCollectedPaths } from './common/ApiReader';
import type { ReseverdSetForArkguard } from './common/ApiReader';
import { ApiExtractor } from './common/ApiExtractor';
import esInfo from './configs/preset/es_reserved_properties.json';
import optimizeEsInfo from './configs/preset/es_reserved_properties_optimized.json';
import {
TimeSumPrinter,
TimeTracker,
endFilesEvent,
endSingleFileEvent,
initPerformancePrinter,
startFilesEvent,
startSingleFileEvent,
} from './utils/PrinterUtils';
import { ObConfigResolver } from './initialization/ConfigResolver';
import {
EventList,
TimeAndMemTimeTracker,
clearTimeAndMemPrinterData,
disablePrinterTimeAndMemConfig,
initPerformanceTimeAndMemPrinter,
} from './utils/PrinterTimeAndMemUtils';
export {
TimeSumPrinter,
blockPrinter,
endFilesEvent,
endSingleFileEvent,
printTimeSumData,
printTimeSumInfo,
startFilesEvent,
startSingleFileEvent,
} from './utils/PrinterUtils';
export {
EventList,
PerfMode,
TimeAndMemTimeTracker,
blockTimeAndMemPrinter,
configurePerformancePrinter,
enableTimeAndMemoryPrint,
} from './utils/PrinterTimeAndMemUtils';
import { Extension, type ProjectInfo, type FilePathObj } from './common/type';
export { type HvigorErrorInfo } from './common/type';
export { FileUtils, type FileInfo, type GetCachedFileInfo } from './utils/FileUtils';
export { MemoryUtils } from './utils/MemoryUtils';
import { TypeUtils } from './utils/TypeUtils';
import { handleReservedConfig } from './utils/TransformUtil';
import { UnobfuscationCollections } from './utils/CommonCollections';
import { FilePathManager, FileContentManager, initProjectWhiteListManager } from './utils/ProjectCollections';
import { clearHistoryUnobfuscatedMap, historyAllUnobfuscatedNamesMap } from './initialization/Initializer';
import { MemoryDottingDefine } from './utils/MemoryDottingDefine';
import { nodeSymbolMap } from './utils/ScopeAnalyzer';
import { clearUnobfuscationNamesObj } from './initialization/CommonObject';
export { UnobfuscationCollections } from './utils/CommonCollections';
export * as ProjectCollections from './utils/ProjectCollections';
export { separateUniversalReservedItem, containWildcards, wildcardTransformer } from './utils/TransformUtil';
export type { ReservedNameInfo } from './utils/TransformUtil';
export type { ReseverdSetForArkguard } from './common/ApiReader';
export { initObfuscationConfig, printerTimeAndMemDataConfig } from './initialization/Initializer';
export { nameCacheMap, unobfuscationNamesObj } from './initialization/CommonObject';
export {
collectResevedFileNameInIDEConfig,
enableObfuscatedFilePathConfig,
enableObfuscateFileName,
generateConsumerObConfigFile,
getRelativeSourcePath,
handleObfuscatedFilePath,
handleUniversalPathInObf,
mangleFilePath,
MergedConfig,
ObConfigResolver,
readNameCache,
clearNameCache,
writeObfuscationNameCache,
writeUnobfuscationContent
} from './initialization/ConfigResolver';
export {
collectReservedNameForObf
} from './utils/NodeUtils';
export {
addReservedFileNames
} from './transformers/rename/RenameFileNameTransformer';
export const renameIdentifierModule = require('./transformers/rename/RenameIdentifierTransformer');
export const renameFileNameModule = require('./transformers/rename/RenameFileNameTransformer');
export { getMapFromJson, readProjectPropertiesByCollectedPaths, deleteLineInfoForNameString, ApiExtractor, PropCollections };
export let orignalFilePathForSearching: string | undefined;
export let cleanFileMangledNames: boolean = false;
export interface PerformancePrinter {
filesPrinter?: TimeTracker;
singleFilePrinter?: TimeTracker;
timeSumPrinter?: TimeSumPrinter;
}
export interface PerformanceTimeAndMemPrinter {
filesPrinter?: TimeAndMemTimeTracker;
singleFilePrinter?: TimeAndMemTimeTracker;
}
export let performancePrinter: PerformancePrinter = {
filesPrinter: new TimeTracker(),
singleFilePrinter: new TimeTracker(),
timeSumPrinter: new TimeSumPrinter(),
};
export let performanceTimeAndMemPrinter: PerformanceTimeAndMemPrinter = {
filesPrinter: new TimeAndMemTimeTracker(),
singleFilePrinter: new TimeAndMemTimeTracker(),
};
export function clearGlobalCaches(): void {
PropCollections.clearPropsCollections();
UnobfuscationCollections.clear();
LocalVariableCollections.clear();
AtKeepCollections.clear();
AtIntentCollections.clear();
renameFileNameModule.clearCaches();
clearUnobfuscationNamesObj();
clearHistoryUnobfuscatedMap();
clearTimeAndMemPrinterData();
disablePrinterTimeAndMemConfig();
ApiExtractor.mConstructorPropertySet.clear();
ApiExtractor.mEnumMemberSet.clear();
BytecodeObfuscationCollections.clear();
}
export type ObfuscationResultType = {
content: string;
sourceMap?: RawSourceMap;
nameCache?: { [k: string]: string | {} };
filePath?: string;
unobfuscationNameMap?: Map<string, Set<string>>;
};
export interface RecordInfo {
recordStage: string;
recordIndex: number;
};
const JSON_TEXT_INDENT_LENGTH: number = 2;
export class ArkObfuscator {
protected mWriteOriginalFile: boolean = false;
private mTextWriter: EmitTextWriter;
private readonly mCompilerOptions: CompilerOptions;
protected mCustomProfiles: IOptions;
private mTransformers: TransformerFactory<Node>[];
private static memoryDottingCallback: (stage: string) => RecordInfo;
private static memoryDottingStopCallback: (recordInfo: RecordInfo) => void;
static mProjectInfo: ProjectInfo | undefined;
static mIsKeptCurrentFile: boolean = false;
public isIncremental: boolean = false;
public shouldReObfuscate: boolean = false;
public filePathManager: FilePathManager | undefined;
public fileContentManager: FileContentManager | undefined;
public obfConfigResolver: ObConfigResolver;
public constructor() {
this.mCompilerOptions = {};
this.mTransformers = [];
}
public getWriteOriginalFileForTest(): boolean {
return this.mWriteOriginalFile;
}
public setWriteOriginalFile(flag: boolean): void {
this.mWriteOriginalFile = flag;
}
public addReservedSetForPropertyObf(properties: ReseverdSetForArkguard): void {
if (properties.structPropertySet && properties.structPropertySet.size > 0) {
for (let reservedProperty of properties.structPropertySet) {
UnobfuscationCollections.reservedStruct.add(reservedProperty);
}
}
if (properties.stringPropertySet && properties.stringPropertySet.size > 0) {
UnobfuscationCollections.reservedStrProp = properties.stringPropertySet;
}
if (properties.objectPropertySet && properties.objectPropertySet.size > 0) {
UnobfuscationCollections.reservedObjProp = properties.objectPropertySet;
}
if (properties.exportNameAndPropSet && properties.exportNameAndPropSet.size > 0) {
UnobfuscationCollections.reservedExportNameAndProp = properties.exportNameAndPropSet;
}
if (properties.enumPropertySet && properties.enumPropertySet.size > 0) {
for (let reservedEnum of properties.enumPropertySet) {
UnobfuscationCollections.reservedEnum.add(reservedEnum);
}
}
}
public addReservedSetForDefaultObf(properties: ReseverdSetForArkguard): void {
if (properties.exportNameSet && properties.exportNameSet.size > 0) {
UnobfuscationCollections.reservedExportName = properties.exportNameSet;
}
}
public setKeepSourceOfPaths(mKeepSourceOfPaths: Set<string>): void {
this.mCustomProfiles.mKeepFileSourceCode.mKeepSourceOfPaths = mKeepSourceOfPaths;
}
public handleTsHarComments(sourceFile: SourceFile, originalPath: string | undefined): void {
if (ArkObfuscator.projectInfo?.useTsHar && (originalPath?.endsWith(Extension.ETS) && !originalPath?.endsWith(Extension.DETS))) {
sourceFile.writeTsHarComments = true;
}
}
public get customProfiles(): IOptions {
return this.mCustomProfiles;
}
public static get isKeptCurrentFile(): boolean {
return ArkObfuscator.mIsKeptCurrentFile;
}
public static set isKeptCurrentFile(isKeptFile: boolean) {
ArkObfuscator.mIsKeptCurrentFile = isKeptFile;
}
public static get projectInfo(): ProjectInfo {
return ArkObfuscator.mProjectInfo;
}
public static set projectInfo(projectInfo: ProjectInfo) {
ArkObfuscator.mProjectInfo = projectInfo;
}
public static recordStage(stage: string): RecordInfo | null {
if (ArkObfuscator.memoryDottingCallback) {
return ArkObfuscator.memoryDottingCallback(stage);
}
return null;
}
public static stopRecordStage(recordInfo: RecordInfo | null): void {
if (ArkObfuscator.memoryDottingStopCallback) {
if (recordInfo !== null) {
ArkObfuscator.memoryDottingStopCallback(recordInfo);
}
}
}
public isCurrentFileInKeepPathsForTest(customProfiles: IOptions, originalFilePath: string): boolean {
return this.isCurrentFileInKeepPaths(customProfiles, originalFilePath);
}
private isCurrentFileInKeepPaths(customProfiles: IOptions, originalFilePath: string): boolean {
const keepFileSourceCode = customProfiles.mKeepFileSourceCode;
if (keepFileSourceCode === undefined || keepFileSourceCode.mKeepSourceOfPaths.size === 0) {
return false;
}
const keepPaths: Set<string> = keepFileSourceCode.mKeepSourceOfPaths;
const originalPath = FileUtils.toUnixPath(originalFilePath);
return keepPaths.has(originalPath);
}
* init ArkObfuscator according to user config
* should be called after constructor
*/
public init(config: IOptions | undefined, cachePath?: string): boolean {
if (!config) {
console.error('obfuscation config file is not found and no given config.');
return false;
}
handleReservedConfig(config, 'mRenameFileName', 'mReservedFileNames', 'mUniversalReservedFileNames');
handleReservedConfig(config, 'mRemoveDeclarationComments', 'mReservedComments', 'mUniversalReservedComments', 'mEnable');
handleReservedConfig(config, 'mRemoveNoSideEffectsCalls', 'mRemovedCallNames', 'mUniversalRemovedCallNames', undefined, false);
this.mCustomProfiles = config;
if (this.mCustomProfiles.mCompact) {
this.mTextWriter = createObfTextSingleLineWriter();
} else {
this.mTextWriter = createTextWriter('\n');
}
if (this.mCustomProfiles.mEnableSourceMap) {
this.mCompilerOptions.sourceMap = true;
}
if (this.mCustomProfiles.mAllowEtsAnnotations) {
this.mCompilerOptions.etsAnnotationsEnable = true;
}
const enableTopLevel: boolean = this.mCustomProfiles.mNameObfuscation?.mTopLevel;
const exportObfuscation: boolean = this.mCustomProfiles.mExportObfuscation;
const propertyObfuscation: boolean = this.mCustomProfiles.mNameObfuscation?.mRenameProperties;
* clean mangledNames in case skip name check when generating names
*/
cleanFileMangledNames = enableTopLevel && !exportObfuscation && !propertyObfuscation;
this.mTransformers = new TransformerManager(this.mCustomProfiles).getTransformers();
initPerformancePrinter(this.mCustomProfiles);
initPerformanceTimeAndMemPrinter();
if (needReadApiInfo(this.mCustomProfiles)) {
let languageSet: Set<string> = new Set();
let presetLanguageWhitelist = this.mCustomProfiles.mStripLanguageDefaultWhitelist ? optimizeEsInfo : esInfo;
for (const key of Object.keys(presetLanguageWhitelist)) {
const valueArray = presetLanguageWhitelist[key];
valueArray.forEach((element: string) => {
languageSet.add(element);
});
}
UnobfuscationCollections.reservedLangForProperty = languageSet;
}
if (cachePath) {
this.initIncrementalCache(
cachePath,
!!this.mCustomProfiles.mNameObfuscation.mEnableAtKeep,
!!this.mCustomProfiles.mNameObfuscation.mKeepObjectProperty
);
}
return true;
}
public static setMemoryDottingCallBack(memoryDottingCallback: (stage: string) => RecordInfo,
memoryDottingStopCallback: (recordInfo: RecordInfo) => void): void {
if (memoryDottingCallback) {
ArkObfuscator.memoryDottingCallback = memoryDottingCallback;
}
if (memoryDottingStopCallback) {
ArkObfuscator.memoryDottingStopCallback = memoryDottingStopCallback;
}
}
public static clearMemoryDottingCallBack(): void {
ArkObfuscator.memoryDottingCallback = undefined;
ArkObfuscator.memoryDottingStopCallback = undefined;
}
* Init incremental cache according to cachePath
*/
private initIncrementalCache(cachePath: string, enableAtKeep: boolean, keepObjectProperty: boolean): void {
this.filePathManager = new FilePathManager(cachePath);
this.isIncremental = this.filePathManager.isIncremental();
this.fileContentManager = new FileContentManager(cachePath, this.isIncremental);
initProjectWhiteListManager(cachePath, this.isIncremental, enableAtKeep, keepObjectProperty);
}
* A Printer to output obfuscated codes.
*/
public createObfsPrinter(isDeclarationFile: boolean): Printer {
let printerOptions: PrinterOptions = {};
let removeOption = this.mCustomProfiles.mRemoveDeclarationComments;
let hasReservedList = removeOption?.mReservedComments?.length || removeOption?.mUniversalReservedComments?.length;
let keepDeclarationComments = hasReservedList || !removeOption?.mEnable;
if (isDeclarationFile && keepDeclarationComments) {
printerOptions.removeComments = false;
}
if ((!isDeclarationFile && this.mCustomProfiles.mRemoveComments) || (isDeclarationFile && !keepDeclarationComments)) {
printerOptions.removeComments = true;
}
return createPrinter(printerOptions);
}
protected isObfsIgnoreFile(fileName: string): boolean {
let suffix: string = FileUtils.getFileExtension(fileName);
return suffix !== 'js' && suffix !== 'ts' && suffix !== 'ets';
}
private convertLineBasedOnSourceMap(targetCache: string, sourceMapLink?: SourceMapLink): Map<string, string> {
let originalCache: Map<string, string> = renameIdentifierModule.nameCache.get(targetCache);
let updatedCache: Map<string, string> = new Map<string, string>();
for (const [key, value] of originalCache) {
if (!key.includes(':')) {
updatedCache[key] = value;
continue;
}
const [scopeName, oldStartLine, oldStartColumn, oldEndLine, oldEndColumn] = key.split(':');
let newKey: string = key;
if (!sourceMapLink) {
newKey = `${scopeName}:${oldStartLine}:${oldEndLine}`;
updatedCache[newKey] = value;
continue;
}
const parts = scopeName.split('#');
const lastScopeName: string = parts[parts.length - 1];
const startPosition: SourceMapSegmentObj | null = sourceMapLink.traceSegment(
Number(oldStartLine) - 1, Number(oldStartColumn) - 1, '');
if (!startPosition && lastScopeName === value) {
continue;
}
const endPosition: SourceMapSegmentObj | null = sourceMapLink.traceSegment(
Number(oldEndLine) - 1, Number(oldEndColumn) - 1, '');
if (!endPosition && lastScopeName === value) {
continue;
}
if (!startPosition || !endPosition) {
updatedCache[scopeName] = value;
} else {
const startLine = startPosition.line + 1;
const endLine = endPosition.line + 1;
newKey = `${scopeName}:${startLine}:${endLine}`;
updatedCache[newKey] = value;
}
}
return updatedCache;
}
public convertLineBasedOnSourceMapForTest(
targetCache: string,
sourceMapLink?: SourceMapLink
): Map<string, string> {
return this.convertLineBasedOnSourceMap(targetCache, sourceMapLink);
}
* Obfuscate ast of a file.
* @param content ast or source code of a source file
* @param sourceFilePathObj
* @param previousStageSourceMap
* @param historyNameCache
* @param originalFilePath When filename obfuscation is enabled, it is used as the source code path.
*/
public async obfuscate(
content: SourceFile | string,
sourceFilePathObj: FilePathObj,
previousStageSourceMap?: RawSourceMap,
historyNameCache?: Map<string, string>,
originalFilePath?: string,
projectInfo?: ProjectInfo,
): Promise<ObfuscationResultType> {
startFilesEvent(EventList.CONFIG_INITIALIZATION);
ArkObfuscator.projectInfo = projectInfo;
let result: ObfuscationResultType = { content: undefined };
if (this.isObfsIgnoreFile(sourceFilePathObj.buildFilePath)) {
endFilesEvent(EventList.CONFIG_INITIALIZATION);
return result;
}
let ast: SourceFile = this.createAst(content, sourceFilePathObj.buildFilePath);
if (ast.statements.length === 0) {
endFilesEvent(EventList.CONFIG_INITIALIZATION);
return result;
}
if (historyNameCache && historyNameCache.size > 0 && this.mCustomProfiles.mNameObfuscation) {
renameIdentifierModule.historyNameCache = historyNameCache;
}
if (this.mCustomProfiles.mUnobfuscationOption?.mPrintKeptNames) {
let historyUnobfuscatedNames = historyAllUnobfuscatedNamesMap.get(sourceFilePathObj.relativeFilePath);
if (historyUnobfuscatedNames) {
renameIdentifierModule.historyUnobfuscatedNamesMap = new Map(Object.entries(historyUnobfuscatedNames));
}
}
originalFilePath = originalFilePath ?? ast.fileName;
if (this.mCustomProfiles.mRenameFileName?.mEnable) {
orignalFilePathForSearching = originalFilePath;
}
ArkObfuscator.isKeptCurrentFile = this.isCurrentFileInKeepPaths(this.mCustomProfiles, originalFilePath);
endFilesEvent(EventList.CONFIG_INITIALIZATION);
this.handleDeclarationFile(ast);
ast = this.obfuscateAst(ast);
startSingleFileEvent(EventList.WRITE_OBFUSCATION_RESULT);
this.writeObfuscationResult(ast, sourceFilePathObj.buildFilePath, result, previousStageSourceMap, originalFilePath);
endSingleFileEvent(EventList.WRITE_OBFUSCATION_RESULT);
this.clearCaches();
return result;
}
private createAst(content: SourceFile | string, sourceFilePath: string): SourceFile {
const recordInfo = ArkObfuscator.recordStage(MemoryDottingDefine.CREATE_AST);
startSingleFileEvent(EventList.CREATE_AST, performancePrinter.timeSumPrinter);
let ast: SourceFile;
if (typeof content === 'string') {
ast = TypeUtils.createObfSourceFile(sourceFilePath, content, this.mCompilerOptions);
} else {
ast = content;
}
endSingleFileEvent(EventList.CREATE_AST, performancePrinter.timeSumPrinter);
ArkObfuscator.stopRecordStage(recordInfo);
return ast;
}
private obfuscateAst(ast: SourceFile): SourceFile {
const recordInfo = ArkObfuscator.recordStage(MemoryDottingDefine.OBFUSCATE_AST);
startSingleFileEvent(EventList.OBFUSCATE_AST, performancePrinter.timeSumPrinter);
let transformedResult: TransformationResult<Node> = transform(ast, this.mTransformers, this.mCompilerOptions);
endSingleFileEvent(EventList.OBFUSCATE_AST, performancePrinter.timeSumPrinter);
ArkObfuscator.stopRecordStage(recordInfo);
ast = transformedResult.transformed[0] as SourceFile;
return ast;
}
private handleDeclarationFile(ast: SourceFile): void {
if (ast.isDeclarationFile) {
if (!this.mCustomProfiles.mRemoveDeclarationComments || !this.mCustomProfiles.mRemoveDeclarationComments.mEnable) {
ast.reservedComments = undefined;
ast.universalReservedComments = undefined;
} else {
ast.reservedComments ??= this.mCustomProfiles.mRemoveDeclarationComments.mReservedComments ?
this.mCustomProfiles.mRemoveDeclarationComments.mReservedComments : [];
ast.universalReservedComments = this.mCustomProfiles.mRemoveDeclarationComments.mUniversalReservedComments ?? [];
}
} else {
ast.reservedComments = this.mCustomProfiles.mRemoveComments ? [] : undefined;
ast.universalReservedComments = this.mCustomProfiles.mRemoveComments ? [] : undefined;
}
}
* write obfuscated code, sourcemap and namecache
*/
private writeObfuscationResult(ast: SourceFile, sourceFilePath: string, result: ObfuscationResultType,
previousStageSourceMap?: RawSourceMap, originalFilePath?: string): void {
let sourceMapGenerator: SourceMapGenerator = undefined;
if (this.mCustomProfiles.mEnableSourceMap) {
startSingleFileEvent(EventList.GET_SOURCEMAP_GENERATOR, performancePrinter.timeSumPrinter);
sourceMapGenerator = getSourceMapGenerator(sourceFilePath);
endSingleFileEvent(EventList.GET_SOURCEMAP_GENERATOR, performancePrinter.timeSumPrinter);
}
if (sourceFilePath.endsWith('.js')) {
TypeUtils.tsToJs(ast);
}
this.handleTsHarComments(ast, originalFilePath);
const recordInfo = ArkObfuscator.recordStage(MemoryDottingDefine.CREATE_PRINTER);
startSingleFileEvent(EventList.CREATE_PRINTER, performancePrinter.timeSumPrinter);
this.createObfsPrinter(ast.isDeclarationFile).writeFile(ast, this.mTextWriter, sourceMapGenerator);
endSingleFileEvent(EventList.CREATE_PRINTER, performancePrinter.timeSumPrinter);
ArkObfuscator.stopRecordStage(recordInfo);
startSingleFileEvent(EventList.GET_OBFUSCATED_CODE);
result.filePath = ast.fileName;
result.content = this.mTextWriter.getText();
endSingleFileEvent(EventList.GET_OBFUSCATED_CODE);
if (this.mCustomProfiles.mUnobfuscationOption?.mPrintKeptNames) {
this.handleUnobfuscationNames(result);
}
startSingleFileEvent(EventList.PROCESS_SOURCEMAP);
if (this.mCustomProfiles.mEnableSourceMap && sourceMapGenerator) {
this.handleSourceMapAndNameCache(sourceMapGenerator, sourceFilePath, result, previousStageSourceMap);
}
endSingleFileEvent(EventList.PROCESS_SOURCEMAP);
}
private handleUnobfuscationNames(result: ObfuscationResultType): void {
result.unobfuscationNameMap = new Map(UnobfuscationCollections.unobfuscatedNamesMap);
}
private handleSourceMapAndNameCache(sourceMapGenerator: SourceMapGenerator, sourceFilePath: string,
result: ObfuscationResultType, previousStageSourceMap?: RawSourceMap): void {
startSingleFileEvent(EventList.SOURCEMAP_MERGE, performancePrinter.timeSumPrinter);
let sourceMapJson: RawSourceMap = sourceMapGenerator.toJSON();
sourceMapJson.sourceRoot = '';
sourceMapJson.file = path.basename(sourceFilePath);
if (previousStageSourceMap) {
sourceMapJson = mergeSourceMap(previousStageSourceMap as RawSourceMap, sourceMapJson);
}
result.sourceMap = sourceMapJson;
endSingleFileEvent(EventList.SOURCEMAP_MERGE, performancePrinter.timeSumPrinter);
startSingleFileEvent(EventList.CREATE_NAMECACHE, performancePrinter.timeSumPrinter);
let nameCache = renameIdentifierModule.nameCache;
if (this.mCustomProfiles.mEnableNameCache) {
let newIdentifierCache!: Object;
let newMemberMethodCache!: Object;
if (previousStageSourceMap) {
const sourceFileName = previousStageSourceMap.sources?.length === 1 ? previousStageSourceMap.sources[0] : '';
const source: Source = new Source(sourceFileName, null);
const decodedSourceMap: ExistingDecodedSourceMap = decodeSourcemap(previousStageSourceMap);
let sourceMapLink: SourceMapLink = new SourceMapLink(decodedSourceMap, [source]);
newIdentifierCache = this.convertLineBasedOnSourceMap(IDENTIFIER_CACHE, sourceMapLink);
newMemberMethodCache = this.convertLineBasedOnSourceMap(MEM_METHOD_CACHE, sourceMapLink);
} else {
newIdentifierCache = this.convertLineBasedOnSourceMap(IDENTIFIER_CACHE);
newMemberMethodCache = this.convertLineBasedOnSourceMap(MEM_METHOD_CACHE);
}
nameCache.set(IDENTIFIER_CACHE, newIdentifierCache);
nameCache.set(MEM_METHOD_CACHE, newMemberMethodCache);
result.nameCache = { [IDENTIFIER_CACHE]: newIdentifierCache, [MEM_METHOD_CACHE]: newMemberMethodCache };
}
endSingleFileEvent(EventList.CREATE_NAMECACHE, performancePrinter.timeSumPrinter);
}
private clearCaches(): void {
this.mTextWriter.clear();
renameIdentifierModule.clearCaches();
if (cleanFileMangledNames) {
PropCollections.globalMangledTable.clear();
}
UnobfuscationCollections.unobfuscatedNamesMap.clear();
nodeSymbolMap.clear();
}
}