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 {performancePrinter} from '../../ArkObfuscator'; 40import {EventList} from '../../utils/PrinterUtils'; 41 42namespace secharmony { 43 export let transformerPlugin: TransformPlugin = { 44 'name': 'VirtualConstructorTransformerFactory', 45 'order': TransformerOrder.VIRTUAL_CONSTRUCTOR_TRANSFORMER, 46 'createTransformerFactory': (option: IOptions) => virtualConstructorTransformerFactory, 47 }; 48} 49 50function virtualConstructorTransformerFactory(context: TransformationContext): Transformer<Node> { 51 return (node: SourceFile) => virtualConstructorTransformer(node, context); 52} 53 54function virtualConstructorTransformer(node: SourceFile, context: TransformationContext): Node { 55 if (!NodeUtils.isDETSFile(node)) { 56 return node; 57 } 58 performancePrinter?.singleFilePrinter?.startEvent(EventList.VIRTUAL_CONSTRUCTOR_OBFUSCATION, 59 performancePrinter.timeSumPrinter); 60 let astWithoutVirtualConstructor = removeVirtualConstructor(node, context); 61 let parentNodes = setParentRecursive(astWithoutVirtualConstructor, true); 62 performancePrinter?.singleFilePrinter?.endEvent(EventList.VIRTUAL_CONSTRUCTOR_OBFUSCATION, 63 performancePrinter.timeSumPrinter); 64 return parentNodes; 65} 66 67function removeVirtualConstructor(node: Node, context: TransformationContext): Node { 68 if (isStructDeclaration(node)) { 69 const tempStructMembers: ClassElement[] = node.members.filter((member) => !isVirtualConstructor(member)); 70 const structMembersWithoutVirtualConstructor = factory.createNodeArray(tempStructMembers); 71 72 return factory.updateStructDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, 73 structMembersWithoutVirtualConstructor); 74 } 75 return visitEachChild(node, (childNode) => removeVirtualConstructor(childNode, context), context); 76} 77 78function isVirtualConstructor(node: Node): boolean { 79 const originalNode = getOriginalNode(node); 80 //@ts-ignore 81 return isConstructorDeclaration(originalNode) && originalNode.virtual; 82} 83 84export = secharmony; 85