• 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 type {INameGenerator, NameGeneratorOptions} from './INameGenerator';
17
18/**
19 * need reserved keyword which contain transformDict character
20 */
21const gReservedIdentifier = [
22  'let', 'return', 'break', 'continue', 'const', 'var', 'console', 'enum',
23  'boolean', 'number', 'string', 'any', 'void', 'undefined', 'null',
24  'never', 'function', 'declare', 'as', 'while', 'for', 'if', 'else',
25  'true', 'false', 'try', 'catch', 'throw', 'type', 'class', 'new',
26  'interface', 'export', 'readonly', 'private', 'public', 'extends',
27  'implements', 'constructor', 'this', 'static', 'protected', 'switch',
28  'case', 'default', 'typeof', 'instanceof', 'in', 'of', 'import', 'require',
29  'module', 'from', 'abstract', 'async', 'namespace', 'arguments', '__global'
30];
31
32const gTransformDict = {
33  'a': 'α',
34  'b': 'þ',
35  'c': 'ç',
36  'e': 'è',
37  'i': 'ì',
38  'k': 'κ',
39  'l': 'ι',
40  'n': 'η',
41  'o': 'ο',
42  'p': 'ρ',
43  'u': 'υ',
44  'v': 'ν',
45  'w': 'ω',
46  'x': 'χ',
47  'y': 'γ',
48  'z': 'ζ'
49};
50
51/**
52 * @Desc: a name generator which use reserved keywords similar words to get obfuscated name
53 */
54export class ReservedNameGenerator implements INameGenerator {
55  private readonly mReservedNames: Set<string>;
56  private readonly mTransformSet: Set<string>;
57
58  private mIdIndex: number;
59  private readonly mWordInfo: number[];
60  private mWordIndex: number;
61
62  constructor(options?: NameGeneratorOptions) {
63    this.mTransformSet = new Set<string>();
64
65    this.mReservedNames = options?.reservedNames;
66
67    const dictKeys: string[] = Object.keys(gTransformDict);
68    for (const key of dictKeys) {
69      this.mTransformSet.add(key);
70    }
71
72    this.mIdIndex = 0;
73    this.mWordIndex = 1;
74    this.mWordInfo = [];
75
76    this.getWordInfo(gReservedIdentifier[this.mIdIndex]);
77  }
78
79  private getWordInfo(originName: string): void {
80    for (let i = 0; i < originName.length; i++) {
81      if (this.mTransformSet.has(originName[i])) {
82        this.mWordInfo.push(i);
83      }
84    }
85  }
86
87  private transformName(originName: string): string {
88    let charArr: string[] = originName.split('');
89    const BINARY_RADIX: number = 2;
90    let binaryArr: string = this.mWordIndex.toString(BINARY_RADIX).split('').reverse().join('');
91    for (let i = 0; i < binaryArr.length; i++) {
92      if (binaryArr[i] === '1') {
93        charArr[this.mWordInfo[i]] = gTransformDict[charArr[this.mWordInfo[i]]];
94      }
95    }
96
97    this.mWordIndex += 1;
98    if (this.mWordIndex === Math.pow(BINARY_RADIX, this.mWordInfo.length)) {
99      this.mIdIndex += 1;
100      this.mWordInfo.length = 0;
101      this.mWordIndex = 1;
102
103      if (this.mIdIndex < gReservedIdentifier.length) {
104        this.getWordInfo(gReservedIdentifier[this.mIdIndex]);
105      }
106    }
107
108    return charArr.join('');
109  }
110
111  /**
112   * @return: null for end
113   */
114  public getName(): string {
115    let originName: string = gReservedIdentifier[this.mIdIndex];
116
117    let transformedName: string = this.transformName(originName);
118    if (this.mIdIndex >= gReservedIdentifier.length) {
119      return null;
120    }
121
122    if (this.mReservedNames?.has(transformedName)) {
123      return this.getName();
124    }
125
126    return transformedName;
127  }
128
129  public reset(): void {
130    this.mIdIndex = 0;
131    this.mWordIndex = 1;
132    this.mWordInfo.length = 0;
133    this.getWordInfo(gReservedIdentifier[this.mIdIndex]);
134  }
135}
136