1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { 17 factory, 18 isStructDeclaration, 19 setParentRecursive, 20 visitEachChild, 21 isConstructorDeclaration, 22 isSourceFile, 23 getOriginalNode 24} from 'typescript'; 25 26import type { 27 ClassElement, 28 Node, 29 SourceFile, 30 TransformationContext, 31 Transformer, 32 TransformerFactory 33} from 'typescript'; 34 35import type {TransformPlugin} from '../TransformPlugin'; 36import {TransformerOrder} from '../TransformPlugin'; 37import type {IOptions} from '../../configs/IOptions'; 38import {NodeUtils} from '../../utils/NodeUtils'; 39import {ArkObfuscator, performancePrinter} from '../../ArkObfuscator'; 40import { EventList, endSingleFileEvent, startSingleFileEvent } from '../../utils/PrinterUtils'; 41import {MemoryDottingDefine} from '../../utils/MemoryDottingDefine'; 42 43namespace secharmony { 44 export let transformerPlugin: TransformPlugin = { 45 'name': 'VirtualConstructorTransformerFactory', 46 'order': TransformerOrder.VIRTUAL_CONSTRUCTOR_TRANSFORMER, 47 'createTransformerFactory': (option: IOptions) => virtualConstructorTransformerFactory, 48 }; 49} 50 51function virtualConstructorTransformerFactory(context: TransformationContext): Transformer<Node> { 52 return (node: SourceFile) => virtualConstructorTransformer(node, context); 53} 54 55function virtualConstructorTransformer(node: SourceFile, context: TransformationContext): Node { 56 if (!NodeUtils.isDETSFile(node)) { 57 return node; 58 } 59 60 const recordInfo = ArkObfuscator.recordStage(MemoryDottingDefine.VIRTUAL_OBFUSCATION); 61 startSingleFileEvent(EventList.VIRTUAL_CONSTRUCTOR_OBFUSCATION, performancePrinter.timeSumPrinter); 62 let astWithoutVirtualConstructor = removeVirtualConstructor(node, context); 63 let parentNodes = setParentRecursive(astWithoutVirtualConstructor, true); 64 endSingleFileEvent(EventList.VIRTUAL_CONSTRUCTOR_OBFUSCATION, performancePrinter.timeSumPrinter); 65 ArkObfuscator.stopRecordStage(recordInfo); 66 return parentNodes; 67} 68 69function removeVirtualConstructor(node: Node, context: TransformationContext): Node { 70 if (isStructDeclaration(node)) { 71 const tempStructMembers: ClassElement[] = node.members.filter((member) => !isVirtualConstructor(member)); 72 const structMembersWithoutVirtualConstructor = factory.createNodeArray(tempStructMembers); 73 74 return factory.updateStructDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, 75 structMembersWithoutVirtualConstructor); 76 } 77 return visitEachChild(node, (childNode) => removeVirtualConstructor(childNode, context), context); 78} 79 80function isVirtualConstructor(node: Node): boolean { 81 const originalNode = getOriginalNode(node); 82 //@ts-ignore 83 return isConstructorDeclaration(originalNode) && originalNode.virtual; 84} 85 86export = secharmony; 87