• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, endSingleFileEvent, startSingleFileEvent } from '../../utils/PrinterUtils';
48import { MemoryDottingDefine } from '../../utils/MemoryDottingDefine';
49
50namespace secharmony {
51  const createShorthandPropertyTransformerFactory = function (option: IOptions): TransformerFactory<Node> | null {
52    let profile: INameObfuscationOption = option.mNameObfuscation;
53    if (!profile || !profile.mEnable) {
54      return null;
55    }
56
57    return shorthandPropertyTransformFactory;
58
59    function shorthandPropertyTransformFactory(context: TransformationContext): Transformer<Node> {
60      return shorthandPropertyTransformer;
61
62      function shorthandPropertyTransformer(node: Node): Node {
63        if (isSourceFile(node) && ArkObfuscator.isKeptCurrentFile) {
64          return node;
65        }
66
67        const recordInfo = ArkObfuscator.recordStage(MemoryDottingDefine.SHORTHAND_OBFUSCATION);
68        startSingleFileEvent(EventList.SHORT_HAND_OBFUSCATION, performancePrinter.timeSumPrinter);
69        let ret = transformShortHandProperty(node);
70        let parentNodes = setParentRecursive(ret, true);
71        endSingleFileEvent(EventList.SHORT_HAND_OBFUSCATION, performancePrinter.timeSumPrinter);
72        ArkObfuscator.stopRecordStage(recordInfo);
73        return parentNodes;
74      }
75
76      function transformShortHandProperty(node: Node): Node {
77        /**
78         * example:
79         * `let name1 = 'hello';`
80         * `let info = {name1};`
81         * obfuscated example:
82         * `let name1 = 'hello';`;
83         * `let info = {name1: name1};`
84         */
85        if (isShorthandPropertyAssignment((node))) {
86          let initializer = node.objectAssignmentInitializer;
87          let expression: Expression = node.name;
88          if (initializer) {
89            expression = factory.createBinaryExpression(node.name, node.equalsToken, initializer);
90          }
91
92          let identifier = factory.createIdentifier(node.name.text);
93          return factory.createPropertyAssignment(identifier, expression);
94        }
95
96        /**
97         * exclude grammar instance: let [name2, age2] = ['akira', 22];
98         *
99         * grammar: {name1, ...rest}= {'name1': 'akira', age : 22};
100         * an alias will be created for name1.
101         * no alias will be created for rest.
102         *
103         * include grammars:
104         * orinal ObjectBinding():
105         * const { name3, age3 } = foo3();
106         * const { name4, addr4: { contry, place} } = foo4();
107         * obfuscated ObjectBinding:
108         * `const { name3: name3, age3: age3 } = foo3();`
109         * `const { name4: name4, addr4: { contry: contry, place: place}  } = { name4: 4, addr4: { contry:5, place:6} };`
110         */
111        if (isElementsInObjectBindingPattern(node) && !node.propertyName && !node.dotDotDotToken) {
112          return factory.createBindingElement(node.dotDotDotToken, factory.createIdentifier((node.name as Identifier).text),
113            node.name, node.initializer);
114        }
115
116        return visitEachChild(node, transformShortHandProperty, context);
117      }
118
119      function isElementsInObjectBindingPattern(node: Node): node is BindingElement {
120        return node.parent && isObjectBindingPattern(node.parent) && isBindingElement(node);
121      }
122    }
123  };
124
125  export let transformerPlugin: TransformPlugin = {
126    'name': 'ShortHandPropertyTransformer',
127    'order': TransformerOrder.SHORTHAND_PROPERTY_TRANSFORMER,
128    'createTransformerFactory': createShorthandPropertyTransformerFactory,
129  };
130}
131
132export = secharmony;
133