1/* 2 * Copyright (c) 2023 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 isBindingElement, 19 isObjectBindingPattern, 20 isShorthandPropertyAssignment, 21 isSourceFile, 22 isStructDeclaration, 23 setParentRecursive, 24 visitEachChild, 25 isConstructorDeclaration 26} from 'typescript'; 27 28import type { 29 BindingElement, 30 ClassElement, 31 Expression, 32 Identifier, 33 Node, 34 SourceFile, 35 StructDeclaration, 36 TransformationContext, 37 Transformer, 38 TransformerFactory 39} from 'typescript'; 40 41import type {INameObfuscationOption} from '../../configs/INameObfuscationOption'; 42import type {TransformPlugin} from '../TransformPlugin'; 43import {TransformerOrder} from '../TransformPlugin'; 44import type {IOptions} from '../../configs/IOptions'; 45import {NodeUtils} from '../../utils/NodeUtils'; 46import {ArkObfuscator, performancePrinter} from '../../ArkObfuscator'; 47import {EventList} from '../../utils/PrinterUtils'; 48 49namespace secharmony { 50 const createShorthandPropertyTransformerFactory = function (option: IOptions): TransformerFactory<Node> { 51 let profile: INameObfuscationOption = option.mNameObfuscation; 52 if (!profile || !profile.mEnable) { 53 return null; 54 } 55 56 return shorthandPropertyTransformFactory; 57 58 function shorthandPropertyTransformFactory(context: TransformationContext): Transformer<Node> { 59 return shorthandPropertyTransformer; 60 61 function shorthandPropertyTransformer(node: Node): Node { 62 if (isSourceFile(node) && ArkObfuscator.isKeptCurrentFile) { 63 return node; 64 } 65 66 performancePrinter?.singleFilePrinter?.startEvent(EventList.SHORT_HAND_OBFUSCATION, performancePrinter.timeSumPrinter); 67 let ret = transformShortHandProperty(node); 68 let parentNodes = setParentRecursive(ret, true); 69 performancePrinter?.singleFilePrinter?.endEvent(EventList.SHORT_HAND_OBFUSCATION, performancePrinter.timeSumPrinter); 70 return parentNodes; 71 } 72 73 function transformShortHandProperty(node: Node): Node { 74 /** 75 * example: 76 * `let name1 = 'hello';` 77 * `let info = {name1};` 78 * obfuscated example: 79 * `let name1 = 'hello';`; 80 * `let info = {name1: name1};` 81 */ 82 if (isShorthandPropertyAssignment((node))) { 83 let initializer = node.objectAssignmentInitializer; 84 let expression: Expression = node.name; 85 if (initializer) { 86 expression = factory.createBinaryExpression(node.name, node.equalsToken, initializer); 87 } 88 89 let identifier = factory.createIdentifier(node.name.text); 90 return factory.createPropertyAssignment(identifier, expression); 91 } 92 93 /** 94 * exclude grammar instance: let [name2, age2] = ['akira', 22]; 95 * 96 * grammar: {name1, ...rest}= {'name1': 'akira', age : 22}; 97 * an alias will be created for name1. 98 * no alias will be created for rest. 99 * 100 * include grammars: 101 * orinal ObjectBinding(): 102 * const { name3, age3 } = foo3(); 103 * const { name4, addr4: { contry, place} } = foo4(); 104 * obfuscated ObjectBinding: 105 * `const { name3: name3, age3: age3 } = foo3();` 106 * `const { name4: name4, addr4: { contry: contry, place: place} } = { name4: 4, addr4: { contry:5, place:6} };` 107 */ 108 if (isElementsInObjectBindingPattern(node) && !node.propertyName && !node.dotDotDotToken) { 109 return factory.createBindingElement(node.dotDotDotToken, factory.createIdentifier((node.name as Identifier).text), 110 node.name, node.initializer); 111 } 112 113 return visitEachChild(node, transformShortHandProperty, context); 114 } 115 116 function isElementsInObjectBindingPattern(node: Node): node is BindingElement { 117 return node.parent && isObjectBindingPattern(node.parent) && isBindingElement(node); 118 } 119 } 120 }; 121 122 export let transformerPlugin: TransformPlugin = { 123 'name': 'ShortHandPropertyTransformer', 124 'order': TransformerOrder.SHORTHAND_PROPERTY_TRANSFORMER, 125 'createTransformerFactory': createShorthandPropertyTransformerFactory, 126 }; 127} 128 129export = secharmony; 130