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