From c27441013f35e2c5dd80ab68aaa64da9253296f1 Mon Sep 17 00:00:00 2001 From: dengxinyu Date: Sat, 2 Nov 2024 21:21:57 +0800 Subject: [PATCH] Fix codecheck for printer optimization Issue: https://gitee.com/openharmony/developtools_ace_ets2bundle/issues/IB1MSS Test: ut & arkTest Signed-off-by: dengxinyu Change-Id: I2a1b0de85104ddffafddaa1f3a8dc4e97f6abc47 --- compiler/src/ark_utils.ts | 51 ++---- .../ark_compiler/common/ob_config_resolver.ts | 94 ++++++++++- .../common/ob_config_resolver.test.ts | 148 +++++++++++++++++- 3 files changed, 253 insertions(+), 40 deletions(-) diff --git a/compiler/src/ark_utils.ts b/compiler/src/ark_utils.ts index 49c1ae1c..aa606a71 100644 --- a/compiler/src/ark_utils.ts +++ b/compiler/src/ark_utils.ts @@ -71,14 +71,20 @@ import { projectConfig, sdkConfigPrefix } from '../main'; -import { getRelativeSourcePath, mangleFilePath } from './fast_build/ark_compiler/common/ob_config_resolver'; +import { + getRelativeSourcePath, + mangleFilePath, + setNewNameCache, + getNameCacheByPath, + setUnobfuscationNames, + writeObfuscatedFile +} from './fast_build/ark_compiler/common/ob_config_resolver'; import { moduleRequestCallback } from './fast_build/system_api/api_check_utils'; import { SourceMapGenerator } from './fast_build/ark_compiler/generate_sourcemap'; import { sourceFileBelongProject } from './fast_build/ark_compiler/module/module_source_file'; const red: string = '\u001b[31m'; const reset: string = '\u001b[39m'; -const IDENTIFIER_CACHE: string = 'IdentifierCache'; export const SRC_MAIN: string = 'src/main'; @@ -484,7 +490,10 @@ function replaceRelativeDependency(item: string, moduleRequest: string, sourcePa return item; } -interface ModuleInfo { +/** + * Informantion of build files + */ +export interface ModuleInfo { content: string, /** * the path in build cache dir @@ -555,16 +564,7 @@ export async function writeArkguardObfuscatedSourceCode(moduleInfo: ModuleInfo, previousStageSourceMap = sourceMapGeneratorInstance.getSpecifySourceMap(rollupNewSourceMaps, selectedFilePath) as sourceMap.RawSourceMap; } - let historyNameCache = new Map(); - let namecachePath = moduleInfo.relativeSourceFilePath; - if (isDeclaration) { - namecachePath = getRelativeSourcePath(moduleInfo.originSourceFilePath, projectRootPath, - sourceFileBelongProject.get(toUnixPath(moduleInfo.originSourceFilePath))); - } - if (nameCacheMap) { - let identifierCache = nameCacheMap.get(namecachePath)?.[IDENTIFIER_CACHE]; - deleteLineInfoForNameString(historyNameCache, identifierCache); - } + const historyNameCache: Map = getNameCacheByPath(moduleInfo, isDeclaration, projectRootPath); let mixedInfo: { content: string, sourceMap?: Object, nameCache?: Object, unobfuscationNameMap?: Map>}; let projectInfo: { @@ -591,35 +591,16 @@ export async function writeArkguardObfuscatedSourceCode(moduleInfo: ModuleInfo, sourceMapGeneratorInstance.updateSpecifySourceMap(rollupNewSourceMaps, selectedFilePath, mixedInfo.sourceMap); } - if (mixedInfo.nameCache && !isDeclaration) { - let obfName: string = moduleInfo.relativeSourceFilePath; - let isOhModule = isPackageModulesFile(moduleInfo.originSourceFilePath, projectConfig); - if (projectConfig.obfuscationMergedObConfig?.options.enableFileNameObfuscation && !isOhModule) { - obfName = mangleFilePath(moduleInfo.relativeSourceFilePath); - } - mixedInfo.nameCache.obfName = obfName; - nameCacheMap.set(moduleInfo.relativeSourceFilePath, mixedInfo.nameCache); - } + setNewNameCache(mixedInfo.nameCache, isDeclaration, moduleInfo, projectConfig); - if (mixedInfo.unobfuscationNameMap && !isDeclaration) { - let arrayObject: Record = {}; - // The type of unobfuscationNameMap's value is Set, convert Set to Array. - mixedInfo.unobfuscationNameMap.forEach((value: Set, key: string) => { - let array: string[] = Array.from(value); - arrayObject[key] = array; - }); - unobfuscationNamesObj[moduleInfo.relativeSourceFilePath] = arrayObject; - } + setUnobfuscationNames(mixedInfo.unobfuscationNameMap, moduleInfo.relativeSourceFilePath, isDeclaration); const newFilePath: string = tryMangleFileName(moduleInfo.buildFilePath, projectConfig, moduleInfo.originSourceFilePath); if (newFilePath !== moduleInfo.buildFilePath && !isDeclaration) { sourceMapGeneratorInstance.saveKeyMappingForObfFileName(moduleInfo.rollupModuleId!); } - performancePrinter?.singleFilePrinter?.startEvent(EventList.WRITE_FILE, performancePrinter.timeSumPrinter); - mkdirsSync(path.dirname(newFilePath)); - fs.writeFileSync(newFilePath, mixedInfo.content ?? ''); - performancePrinter?.singleFilePrinter?.endEvent(EventList.WRITE_FILE, performancePrinter.timeSumPrinter, false, true); + writeObfuscatedFile(newFilePath, mixedInfo.content ?? ''); } export function tryMangleFileName(filePath: string, projectConfig: Object, originalFilePath: string): string { diff --git a/compiler/src/fast_build/ark_compiler/common/ob_config_resolver.ts b/compiler/src/fast_build/ark_compiler/common/ob_config_resolver.ts index a169d753..97d1e7a5 100644 --- a/compiler/src/fast_build/ark_compiler/common/ob_config_resolver.ts +++ b/compiler/src/fast_build/ark_compiler/common/ob_config_resolver.ts @@ -19,16 +19,23 @@ import type * as ts from 'typescript'; import { ApiExtractor, clearGlobalCaches, - performancePrinter + performancePrinter, + getRelativeSourcePath, + nameCacheMap, + deleteLineInfoForNameString, + mangleFilePath, + unobfuscationNamesObj, + EventList } from 'arkguard'; import type { ArkObfuscator, } from 'arkguard'; -import { toUnixPath } from '../../../utils'; +import { isPackageModulesFile, mkdirsSync, toUnixPath } from '../../../utils'; import { allSourceFilePaths, localPackageSet } from '../../../ets_checker'; import { isCurrentProjectFiles } from '../utils'; import { sourceFileBelongProject } from '../module/module_source_file'; +import { ModuleInfo } from '../../../ark_utils'; export { collectResevedFileNameInIDEConfig, // For running unit test. @@ -60,6 +67,11 @@ export function resetObfuscation(): void { */ export const sourceFileDependencies: Map> = new Map(); +/** + * Identifier cache name + */ +export const IDENTIFIER_CACHE: string = 'IdentifierCache'; + // Collect all keep files. If the path configured by the developer is a folder, all files in the compilation will be used to match this folder. function collectAllKeepFiles(startPaths: string[], excludePathSet: Set): Set { const allKeepFiles: Set = new Set(); @@ -144,6 +156,82 @@ export function disablePerformancePrinter(): void { if (performancePrinter !== undefined) { performancePrinter.filesPrinter = undefined; performancePrinter.singleFilePrinter = undefined; - performancePrinter.timeSumPrinter = undefined + performancePrinter.timeSumPrinter = undefined; } +} + +/** + * Get namecache by path + * + * If it is a declaration file, retrieves the corresponding source file's obfuscation results + * Or retrieves obfuscation results from full compilation run + */ +export function getNameCacheByPath( + moduleInfo: ModuleInfo, + isDeclaration: boolean, + projectRootPath: string | undefined +): Map { + let historyNameCache = new Map(); + let nameCachePath = moduleInfo.relativeSourceFilePath; + if (isDeclaration) { + nameCachePath = getRelativeSourcePath( + moduleInfo.originSourceFilePath, + projectRootPath, + sourceFileBelongProject.get(toUnixPath(moduleInfo.originSourceFilePath)) + ); + } + if (nameCacheMap) { + let identifierCache = nameCacheMap.get(nameCachePath)?.[IDENTIFIER_CACHE]; + deleteLineInfoForNameString(historyNameCache, identifierCache); + } + return historyNameCache; +} + +/** + * Set newly updated namecache for project source files + */ +export function setNewNameCache( + newNameCache: Object, + isDeclaration: boolean, + moduleInfo: ModuleInfo, + projectConfig: Object +): void { + if (newNameCache && !isDeclaration) { + let obfName: string = moduleInfo.relativeSourceFilePath; + let isOhModule: boolean = isPackageModulesFile(moduleInfo.originSourceFilePath, projectConfig); + if (projectConfig.obfuscationMergedObConfig?.options.enableFileNameObfuscation && !isOhModule) { + obfName = mangleFilePath(moduleInfo.relativeSourceFilePath); + } + newNameCache.obfName = obfName; + nameCacheMap.set(moduleInfo.relativeSourceFilePath, newNameCache); + } +} + +/** + * Set unobfuscation list after obfuscation + */ +export function setUnobfuscationNames( + unobfuscationNameMap: Map> | undefined, + relativeSourceFilePath: string, + isDeclaration: boolean +): void { + if (unobfuscationNameMap && !isDeclaration) { + let arrayObject: Record = {}; + // The type of unobfuscationNameMap's value is Set, convert Set to Array. + unobfuscationNameMap.forEach((value: Set, key: string) => { + let array: string[] = Array.from(value); + arrayObject[key] = array; + }); + unobfuscationNamesObj[relativeSourceFilePath] = arrayObject; + } +} + +/** + * Write out obfuscated files + */ +export function writeObfuscatedFile(newFilePath: string, content: string): void { + performancePrinter?.singleFilePrinter?.startEvent(EventList.WRITE_FILE, performancePrinter.timeSumPrinter); + mkdirsSync(path.dirname(newFilePath)); + fs.writeFileSync(newFilePath, content); + performancePrinter?.singleFilePrinter?.endEvent(EventList.WRITE_FILE, performancePrinter.timeSumPrinter, false, true); } \ No newline at end of file diff --git a/compiler/test/ark_compiler_ut/common/ob_config_resolver.test.ts b/compiler/test/ark_compiler_ut/common/ob_config_resolver.test.ts index c4ecf3c5..61752756 100644 --- a/compiler/test/ark_compiler_ut/common/ob_config_resolver.test.ts +++ b/compiler/test/ark_compiler_ut/common/ob_config_resolver.test.ts @@ -24,9 +24,14 @@ import { MergedConfig, ObConfigResolver, collectResevedFileNameInIDEConfig, + getNameCacheByPath, getRelativeSourcePath, handleKeepFilesAndGetDependencies, - sourceFileDependencies + setNewNameCache, + setUnobfuscationNames, + sourceFileDependencies, + writeObfuscatedFile, + IDENTIFIER_CACHE } from '../../../lib/fast_build/ark_compiler/common/ob_config_resolver'; import { OBFUSCATION_RULE_PATH, @@ -35,7 +40,7 @@ import { import { OBFUSCATION_TOOL } from '../../../lib/fast_build/ark_compiler/common/ark_define'; import { RELEASE } from '../../../lib/fast_build/ark_compiler/common/ark_define'; import RollUpPluginMock from '../mock/rollup_mock/rollup_plugin_mock'; -import { ArkObfuscator } from 'arkguard'; +import { ArkObfuscator, nameCacheMap, unobfuscationNamesObj } from 'arkguard'; const OBFUSCATE_TESTDATA_DIR = path.resolve(__dirname, '../../../test/ark_compiler_ut/testdata/obfuscation'); @@ -726,4 +731,143 @@ mocha.describe('test obfuscate config resolver api', function () { expect(keepFilesAndDependencies.has(testFile4)).to.be.true; expect(keepFilesAndDependencies.has(testFile5)).to.be.false; }); + + mocha.it('6-1: test getHistoryNameCache: isDeclaration false', function () { + const moduleInfo = { + content: 'module content', + buildFilePath: 'build/path/to/file.ts', + relativeSourceFilePath: 'src/file.ts', + originSourceFilePath: 'C:/projects/my-project/src/file.ts' + }; + nameCacheMap.set('src/file.ts', { + [IDENTIFIER_CACHE]: { + 'identifier1:1': 'obfuscated1', + identifier2: 'obfuscated2' + } + }); + const isDeclaration: boolean = false; + const projectRootPath: string = 'C:/projects/my-project'; + const result: Map = getNameCacheByPath(moduleInfo, isDeclaration, projectRootPath); + nameCacheMap.clear(); + expect(result.size).to.equal(2); + expect(result.get('identifier1')).to.equal('obfuscated1'); + expect(result.get('identifier2')).to.equal('obfuscated2'); + }); + + mocha.it('6-2: test getHistoryNameCache: isDeclaration true', function () { + const moduleInfo = { + content: 'module content', + buildFilePath: 'build/path/to/file.d.ts', + relativeSourceFilePath: 'src/file.ts', + originSourceFilePath: 'C:/projects/my-project/src/file.ts' + }; + nameCacheMap.set('src/file.ts', { + [IDENTIFIER_CACHE]: { + 'identifier1:1': 'obfuscated1', + identifier2: 'obfuscated2' + } + }); + const isDeclaration: boolean = true; + const projectRootPath: string = 'C:/projects/my-project'; + const result: Map = getNameCacheByPath(moduleInfo, isDeclaration, projectRootPath); + nameCacheMap.clear(); + expect(result.size).to.equal(2); + expect(result.get('identifier1')).to.equal('obfuscated1'); + expect(result.get('identifier2')).to.equal('obfuscated2'); + }); + + mocha.it('7-1: test setNewNameCache: isOhModule is false', function () { + const moduleInfo = { + content: 'module content', + buildFilePath: 'build/path/to/file.ts', + relativeSourceFilePath: 'src/file.ts', + originSourceFilePath: 'C:/projects/my-project/src/file.ts' + }; + nameCacheMap.set('src/file.ts', { + [IDENTIFIER_CACHE]: { + 'identifier1:1': 'obfuscated1', + identifier2: 'obfuscated2' + } + }); + const newNameCache = { + [IDENTIFIER_CACHE]: { + 'identifier3:3': 'obfuscated3' + } + }; + const isDeclaration: boolean = false; + const projectConfig: Object = { + obfuscationMergedObConfig: { options: { enableFileNameObfuscation: true } }, + projectRootPath: '/projectRoot', + packageDir: 'oh_modules', + modulePathMap: { + module1: '/externalModule' + }, + }; + setNewNameCache(newNameCache, isDeclaration, moduleInfo, projectConfig); + const result: string | {} = nameCacheMap.get(moduleInfo.relativeSourceFilePath); + nameCacheMap.clear(); + + expect(result[IDENTIFIER_CACHE]['identifier3:3'] === 'obfuscated3').to.be.true; + expect(result.obfName === 'src/file.ts').to.be.false; + }); + + mocha.it('7-2: test setNewNameCache: isOhModule is true', function () { + const moduleInfo = { + content: 'module content', + buildFilePath: 'build/path/to/file.ts', + relativeSourceFilePath: 'src/file.ts', + originSourceFilePath: '/projectRoot/oh_modules/src/file.ts' + }; + nameCacheMap.set('src/file.ts', { + [IDENTIFIER_CACHE]: { + 'identifier1:1': 'obfuscated1', + identifier2: 'obfuscated2' + } + }); + const newNameCache = { + [IDENTIFIER_CACHE]: { + 'identifier3:3': 'obfuscated3' + } + }; + const isDeclaration: boolean = false; + const projectConfig: Object = { + obfuscationMergedObConfig: { options: { enableFileNameObfuscation: true } }, + projectRootPath: '/projectRoot', + packageDir: 'oh_modules' + }; + setNewNameCache(newNameCache, isDeclaration, moduleInfo, projectConfig); + const result: string | {} = nameCacheMap.get(moduleInfo.relativeSourceFilePath); + nameCacheMap.clear(); + + expect(result[IDENTIFIER_CACHE]['identifier3:3'] === 'obfuscated3').to.be.true; + expect(result.obfName === 'src/file.ts').to.be.true; + }); + + mocha.it('8-1: test setUnobfuscationNames', function () { + const relativeSourceFilePath: string = 'src/file.ts'; + const unobfuscationNameMap: Map> = new Map([ + ['key1', new Set(['value1', 'value2'])], + ['key2', new Set(['value3'])] + ]); + const isDeclaration: boolean = false; + + setUnobfuscationNames(unobfuscationNameMap, relativeSourceFilePath, isDeclaration); + + expect(unobfuscationNamesObj[relativeSourceFilePath]).to.deep.equal({ + key1: ['value1', 'value2'], + key2: ['value3'] + }); + }); + + mocha.it('9-1: test writeFile', function () { + const newFilePath: string = '../../test/ark_compiler_ut/testdata/writeFile.ts'; + const content: string = 'obfuscated code'; + + writeObfuscatedFile(newFilePath, content); + + expect(fs.existsSync(newFilePath)).to.be.true; + const fileContent: string = fs.readFileSync(newFilePath, 'utf-8'); + expect(fileContent).to.equal(content); + fs.unlinkSync(newFilePath); + }); }); \ No newline at end of file