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