1/* 2 * Copyright (c) 2024 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 { describe, it } from 'mocha'; 17import { expect } from 'chai'; 18import { NodeUtils, collectReservedNameForObf, hasExportModifier } from '../../../src/utils/NodeUtils'; 19import * as ts from 'typescript' 20import sinon from 'sinon'; 21import { MergedConfig } from '../../../src/initialization/ConfigResolver'; 22import { UnobfuscationCollections } from '../../../src/utils/CommonCollections'; 23 24type Mutable<T extends object> = { -readonly [K in keyof T]: T[K] } 25 26describe('test for NodeUtils', function () { 27 describe('test for isPropertyDeclarationNode', function () { 28 it('should return false if node has no parent', function () { 29 const node = ts.factory.createIdentifier('name'); 30 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.false; 31 }) 32 it('should return ture when node.parent is PropertyAssignment', function () { 33 const node = ts.factory.createIdentifier('name'); 34 const parent = ts.factory.createPropertyAssignment(node, ts.factory.createNumericLiteral('1')); 35 (node as Mutable<ts.Node>).parent = parent; 36 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 37 }) 38 it('should return ture when node.parent is ComputedPropertyName', function () { 39 const node = ts.factory.createIdentifier('name'); 40 const parent = ts.factory.createComputedPropertyName(node); 41 (node as Mutable<ts.Node>).parent = parent; 42 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 43 }) 44 it('should return ture when node.parent is BindingElement', function () { 45 const node = ts.factory.createIdentifier('name'); 46 const parent = ts.factory.createBindingElement(undefined, node, 'bindingElement'); 47 (node as Mutable<ts.Node>).parent = parent; 48 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 49 }) 50 it('should return ture when node.parent is PropertySignature', function () { 51 const node = ts.factory.createIdentifier('name'); 52 const parent = ts.factory.createPropertySignature(undefined, node, undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)); 53 (node as Mutable<ts.Node>).parent = parent; 54 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 55 }) 56 it('should return ture when node.parent is MethodSignature', function () { 57 const node = ts.factory.createIdentifier('name'); 58 const parent = ts.factory.createMethodSignature(undefined, node, undefined, undefined, [], undefined); 59 (node as Mutable<ts.Node>).parent = parent; 60 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 61 }) 62 it('should return ture when node.parent is EnumMember', function () { 63 const node = ts.factory.createIdentifier('name'); 64 const parent = ts.factory.createEnumMember(node); 65 (node as Mutable<ts.Node>).parent = parent; 66 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 67 }) 68 it('should return ture when node.parent is PropertyDeclaration', function () { 69 const node = ts.factory.createIdentifier('name'); 70 const parent = ts.factory.createPropertyDeclaration(undefined, undefined, node, undefined, undefined, undefined); 71 (node as Mutable<ts.Node>).parent = parent; 72 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 73 }) 74 it('should return ture when node.parent is MethodDeclaration', function () { 75 const node = ts.factory.createIdentifier('name'); 76 const parent = ts.factory.createMethodDeclaration(undefined, undefined, undefined, node, undefined, undefined, [], undefined, undefined); 77 (node as Mutable<ts.Node>).parent = parent; 78 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 79 }) 80 it('should return ture when node.parent is SetAccessorDeclaration', function () { 81 const node = ts.factory.createIdentifier('name'); 82 const parent = ts.factory.createSetAccessorDeclaration(undefined, undefined, node, [], undefined); 83 (node as Mutable<ts.Node>).parent = parent; 84 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 85 }) 86 it('should return ture when node.parent is GetAccessorDeclaration', function () { 87 const node = ts.factory.createIdentifier('name'); 88 const parent = ts.factory.createGetAccessorDeclaration(undefined, undefined, node, [], undefined, undefined); 89 (node as Mutable<ts.Node>).parent = parent; 90 expect(NodeUtils.isPropertyDeclarationNode(node)).to.be.true; 91 }) 92 }) 93 describe('test for isPropertyOrElementAccessNode', function () { 94 let isPropertyAccessNodeStub; 95 let isElementAccessNodeStub; 96 97 beforeEach(function () { 98 isPropertyAccessNodeStub = sinon.stub(NodeUtils, 'isPropertyAccessNode').returns(false); 99 isElementAccessNodeStub = sinon.stub(NodeUtils, 'isElementAccessNode').returns(false); 100 }); 101 102 afterEach(function () { 103 isPropertyAccessNodeStub.restore(); 104 isElementAccessNodeStub.restore(); 105 }); 106 107 it('should return true when node is a PropertyAccessNode', function () { 108 const node = ts.factory.createIdentifier('name'); 109 isPropertyAccessNodeStub.returns(true); 110 expect(NodeUtils.isPropertyOrElementAccessNode(node)).to.be.true; 111 }) 112 it('should return true when node is a isElementAccessNode', function () { 113 const node = ts.factory.createIdentifier('name'); 114 isElementAccessNodeStub.returns(true); 115 expect(NodeUtils.isPropertyOrElementAccessNode(node)).to.be.true; 116 }) 117 it('should return false when both isPropertyAccessNode and isElementAccessNode return false', function () { 118 const node = ts.factory.createIdentifier('name'); 119 expect(NodeUtils.isPropertyOrElementAccessNode(node)).to.be.false; 120 }) 121 }) 122 describe('test for isPropertyAccessNode', function () { 123 let isInClassDeclarationStub; 124 let isInExpressionStub; 125 126 beforeEach(function () { 127 isInClassDeclarationStub = sinon.stub(NodeUtils, 'isInClassDeclaration').returns(false); 128 isInExpressionStub = sinon.stub(NodeUtils, 'isInExpression').returns(false); 129 }); 130 131 afterEach(function () { 132 isInClassDeclarationStub.restore(); 133 isInExpressionStub.restore(); 134 }); 135 136 it('should return false if node has no parent', function () { 137 const node = ts.factory.createIdentifier('name'); 138 expect(NodeUtils.isPropertyAccessNode(node)).to.be.false; 139 }) 140 it('should return true if isPropertyAccessExpression and parent.name equals to node', function () { 141 const node = ts.factory.createIdentifier('name'); 142 const parent = ts.factory.createPropertyAccessExpression(node, node); 143 (node as Mutable<ts.Node>).parent = parent; 144 expect(NodeUtils.isPropertyAccessNode(node)).to.be.true; 145 }) 146 it('should return isInExpression(parent) if isPrivateIdentifier and isInClassDeclaration', function () { 147 const node = ts.factory.createPrivateIdentifier("#name"); 148 const parent = ts.factory.createIdentifier('parent'); 149 (node as Mutable<ts.Node>).parent = parent; 150 isInClassDeclarationStub.returns(true); 151 isInExpressionStub.returns(true) 152 expect(NodeUtils.isPropertyAccessNode(node)).to.be.true; 153 isInExpressionStub.returns(false) 154 expect(NodeUtils.isPropertyAccessNode(node)).to.be.false; 155 }) 156 it('should return true if isQualifiedName and parent.right equals to node', function () { 157 const node = ts.factory.createIdentifier('name'); 158 const parent = ts.factory.createQualifiedName(node, node); 159 (node as Mutable<ts.Node>).parent = parent; 160 expect(NodeUtils.isPropertyAccessNode(node)).to.be.true; 161 }) 162 }) 163 describe('test for isInClassDeclaration', function () { 164 it('should return flase when node is undefined', function () { 165 expect(NodeUtils.isInClassDeclarationForTest(undefined)).to.be.false; 166 }) 167 it('should return true when node is ClassDeclaration', function () { 168 const node = ts.factory.createClassDeclaration(undefined, undefined, undefined, undefined, undefined, []); 169 expect(NodeUtils.isInClassDeclarationForTest(node)).to.be.true; 170 }) 171 it('should return true when node is ClassExpression', function () { 172 const node = ts.factory.createClassExpression(undefined, undefined, undefined, undefined, undefined, []); 173 expect(NodeUtils.isInClassDeclarationForTest(node)).to.be.true; 174 }) 175 it('should return true when node.parent is isInClassDeclaration', function () { 176 const node = ts.factory.createIdentifier('name'); 177 const parent = ts.factory.createClassExpression(undefined, undefined, undefined, undefined, undefined, []); 178 (node as Mutable<ts.Node>).parent = parent; 179 expect(NodeUtils.isInClassDeclarationForTest(node)).to.be.true; 180 }) 181 }) 182 describe('test for isInClassDeclaration', function () { 183 it('should return flase when node is undefined', function () { 184 expect(NodeUtils.isInClassDeclarationForTest(undefined)).to.be.false; 185 }) 186 it('should return true when node is ClassDeclaration', function () { 187 const node = ts.factory.createClassDeclaration(undefined, undefined, undefined, undefined, undefined, []); 188 expect(NodeUtils.isInClassDeclarationForTest(node)).to.be.true; 189 }) 190 it('should return true when node is ClassExpression', function () { 191 const node = ts.factory.createClassExpression(undefined, undefined, undefined, undefined, undefined, []); 192 expect(NodeUtils.isInClassDeclarationForTest(node)).to.be.true; 193 }) 194 it('should return true when node.parent is isInClassDeclaration', function () { 195 const node = ts.factory.createIdentifier('name'); 196 const parent = ts.factory.createClassExpression(undefined, undefined, undefined, undefined, undefined, []); 197 (node as Mutable<ts.Node>).parent = parent; 198 expect(NodeUtils.isInClassDeclarationForTest(node)).to.be.true; 199 }) 200 }) 201 describe('test for isInExpression', function () { 202 it('should return flase when node is undefined', function () { 203 expect(NodeUtils.isInExpressionForTest(undefined)).to.be.false; 204 }) 205 it('should return isInOperator(node) when node is not undefined', function () { 206 let isInOperatorStub = sinon.stub(NodeUtils, 'isInOperator').returns(false); 207 const node = ts.factory.createIdentifier('name'); 208 expect(NodeUtils.isInExpressionForTest(node)).to.be.false; 209 isInOperatorStub.returns(true); 210 expect(NodeUtils.isInExpressionForTest(node)).to.be.true; 211 isInOperatorStub.restore(); 212 }) 213 }) 214 describe('test for isInOperator', function () { 215 it('should return true when node is binary expression and operator is InKeyword', function () { 216 const name = ts.factory.createIdentifier('name'); 217 const node = ts.factory.createBinaryExpression(name, ts.SyntaxKind.InKeyword, name); 218 expect(NodeUtils.isInOperatorForTest(node)).to.be.true; 219 }) 220 it('should return false when node is not binary expression', function () { 221 const node = ts.factory.createIdentifier('name'); 222 expect(NodeUtils.isInOperatorForTest(node)).to.be.false; 223 }) 224 it('should return false when operator is not Inkeyword', function () { 225 const name = ts.factory.createIdentifier('name'); 226 const node = ts.factory.createBinaryExpression(name, ts.SyntaxKind.PlusEqualsToken, name); 227 expect(NodeUtils.isInOperatorForTest(node)).to.be.false; 228 }) 229 }) 230 231 describe('test for isElementAccessNode', function () { 232 it('should return false if node has no parent', function () { 233 const node = ts.factory.createIdentifier('name'); 234 expect(NodeUtils.isElementAccessNode(node)).to.be.false; 235 }) 236 it('should return true if isElementAccessExpression and parent argumentExpression equals to node', function () { 237 const node = ts.factory.createIdentifier('name'); 238 const parent = ts.factory.createElementAccessExpression(node, node); 239 (node as Mutable<ts.Node>).parent = parent; 240 expect(NodeUtils.isElementAccessNode(node)).to.be.true; 241 }) 242 }) 243 244 describe('test for isIndexedAccessNode', function () { 245 it('should return false if node has no parent', function () { 246 const node = ts.factory.createIdentifier('name'); 247 expect(NodeUtils.isIndexedAccessNode(node)).to.be.false; 248 }) 249 it('should return false if isIndexedAccessNode but parent literalType not equals to node', function () { 250 const node1 = ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("name")); 251 const node2 = ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(1)); 252 const parent = ts.factory.createIndexedAccessTypeNode(node2, node2); 253 (node1 as Mutable<ts.Node>).parent = parent; 254 (node2 as Mutable<ts.Node>).parent = parent; 255 expect(NodeUtils.isIndexedAccessNode(node1)).to.be.false; 256 expect(NodeUtils.isIndexedAccessNode(node2)).to.be.true; 257 }) 258 it('should return true if isIndexedAccessNode and parent literalType equals to node', function () { 259 const node1 = ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("name")); 260 const node2 = ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(1)); 261 const parent1 = ts.factory.createIndexedAccessTypeNode(node1, node1); 262 const parent2 = ts.factory.createIndexedAccessTypeNode(node2, node2); 263 (node1 as Mutable<ts.Node>).parent = parent1; 264 (node2 as Mutable<ts.Node>).parent = parent2; 265 expect(NodeUtils.isIndexedAccessNode(node1)).to.be.true; 266 expect(NodeUtils.isIndexedAccessNode(node2)).to.be.true; 267 }) 268 }) 269 270 describe('test for isClassPropertyInConstructorParams', function () { 271 it('should return false if node is not an Identifier', function () { 272 const node = ts.factory.createRegularExpressionLiteral('name'); 273 expect(NodeUtils.isClassPropertyInConstructorParams(node)).to.be.false; 274 }) 275 it('should return false when node has no parent', function () { 276 const node = ts.factory.createIdentifier('name'); 277 expect(NodeUtils.isClassPropertyInConstructorParams(node)).to.be.false; 278 }) 279 it('should return false when node parent is not a parameter', function () { 280 const node = ts.factory.createIdentifier('name'); 281 const parent = ts.factory.createElementAccessExpression(node, node); 282 (node as Mutable<ts.Node>).parent = parent; 283 expect(NodeUtils.isClassPropertyInConstructorParams(node)).to.be.false; 284 }) 285 it('should return false when modifiers is undefined', function () { 286 const node = ts.factory.createIdentifier('name'); 287 const parent = ts.factory.createParameterDeclaration([], undefined, node, undefined, undefined, undefined); 288 (node as Mutable<ts.Node>).parent = parent; 289 expect(NodeUtils.isClassPropertyInConstructorParams(node)).to.be.false; 290 }) 291 it('should return false when modifiers length is 0 or modifier is ParameterPropertyModifier', function () { 292 const node = ts.factory.createIdentifier('name'); 293 const parent = ts.factory.createParameterDeclaration([ts.factory.createModifier(ts.SyntaxKind.AbstractKeyword)], undefined, node, undefined, undefined, undefined); 294 (node as Mutable<ts.Node>).parent = parent; 295 expect(NodeUtils.isClassPropertyInConstructorParams(node)).to.be.false; 296 }) 297 it('should return true when node parent parent is ConstructorDeclaration', function () { 298 const node = ts.factory.createIdentifier('name'); 299 const parent = ts.factory.createParameterDeclaration([ts.factory.createModifier(ts.SyntaxKind.PublicKeyword)], undefined, node, undefined, undefined, undefined); 300 const parentParent = ts.factory.createConstructorDeclaration(undefined, [ts.factory.createModifier(ts.SyntaxKind.AbstractKeyword)], [], undefined); 301 (parent as Mutable<ts.Node>).parent = parentParent; 302 (node as Mutable<ts.Node>).parent = parent; 303 expect(NodeUtils.isClassPropertyInConstructorParams(node)).to.be.true; 304 }) 305 }) 306 307 describe('test for isClassPropertyInConstructorBody', function () { 308 it('should return false if node is not an Identifier', function () { 309 const node = ts.factory.createRegularExpressionLiteral('name'); 310 expect(NodeUtils.isClassPropertyInConstructorBody(node, new Set)).to.be.false; 311 }) 312 it('shound return true when node parent is ConstructorDeclaration and constructorParams has id', function () { 313 const node = ts.factory.createIdentifier('name'); 314 const set: Set<string> = new Set(); 315 set.add('name'); 316 const parent = ts.factory.createConstructorDeclaration(undefined, [ts.factory.createModifier(ts.SyntaxKind.AbstractKeyword)], [], undefined); 317 (node as Mutable<ts.Node>).parent = parent; 318 expect(NodeUtils.isClassPropertyInConstructorBody(node, set)).to.be.true; 319 }) 320 it('should return false when curNode is not a ConstructorDeclaration or id does not exist in constructorParams', function () { 321 const node = ts.factory.createIdentifier('name'); 322 const set: Set<string> = new Set(); 323 set.add('test'); 324 const parent = ts.factory.createElementAccessExpression(node, node); 325 (node as Mutable<ts.Node>).parent = parent; 326 expect(NodeUtils.isClassPropertyInConstructorBody(node, set)).to.be.false; 327 }) 328 }) 329 330 describe('test for isPropertyNode', function () { 331 it('should return true when node is PropertyOrElementAccessNode', function () { 332 const node = ts.factory.createIdentifier('name'); 333 const parent = ts.factory.createElementAccessExpression(node, node); 334 (node as Mutable<ts.Node>).parent = parent; 335 expect(NodeUtils.isPropertyNode(node)).to.be.true; 336 }) 337 it('should return true when node is a PropertyDeclarationNode', function () { 338 const node = ts.factory.createIdentifier('name'); 339 const parent = ts.factory.createPropertyAssignment(node, node); 340 (node as Mutable<ts.Node>).parent = parent; 341 expect(NodeUtils.isPropertyNode(node)).to.be.true; 342 }) 343 it('should return true when node is a IndexedAccessNode', function () { 344 const node = ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("name")); 345 const parent = ts.factory.createIndexedAccessTypeNode(node, node); 346 (node as Mutable<ts.Node>).parent = parent; 347 expect(NodeUtils.isPropertyNode(node)).to.be.true; 348 }) 349 }) 350 351 describe('test for isObjectBindingPatternAssignment', function () { 352 it('should return false when node is not VariableDeclaration', function () { 353 const node = ts.factory.createObjectBindingPattern([]); 354 const parent = ts.factory.createParameterDeclaration(undefined, undefined, undefined, node, undefined, undefined, undefined); 355 (node as Mutable<ts.Node>).parent = parent; 356 expect(NodeUtils.isObjectBindingPatternAssignment(node)).to.be.false; 357 }) 358 it('should return true when node parent initializer is CallExpression', function () { 359 const node = ts.factory.createObjectBindingPattern([]); 360 const parent = ts.factory.createVariableDeclaration(node, undefined, undefined, undefined); 361 const initializer = ts.factory.createCallExpression(ts.factory.createIdentifier('name'), undefined, undefined); 362 (parent as Mutable<ts.VariableDeclaration>).initializer = initializer; 363 (node as Mutable<ts.Node>).parent = parent; 364 expect(NodeUtils.isObjectBindingPatternAssignment(node)).to.be.true; 365 }) 366 }) 367 368 describe('test for isDeclarationFile', function () { 369 it('should return false when sourceFile is not a declarationFile', function () { 370 const endOfFileToken = ts.factory.createToken(ts.SyntaxKind.EndOfFileToken); 371 const sourceFile = ts.factory.createSourceFile([], endOfFileToken, ts.NodeFlags.AwaitContext); 372 expect(NodeUtils.isDeclarationFile(sourceFile)).to.be.false; 373 }) 374 }) 375 376 describe('test for getSourceFileOfNode', function () { 377 it('should return node when node kind is SyntaxKind.SourceFile', function () { 378 const node = ts.factory.createIdentifier('name'); 379 const kind = ts.SyntaxKind.SourceFile; 380 (node as Mutable<ts.Node>).kind = kind; 381 expect(NodeUtils.getSourceFileOfNode(node)).to.equal(node); 382 }) 383 it('should return node parent when node kind is not SyntaxKind.SourceFile', function () { 384 const node = ts.factory.createIdentifier('name'); 385 const kind = ts.SyntaxKind.SymbolKeyword; 386 (node as Mutable<ts.Node>).kind = kind; 387 const endOfFileToken = ts.factory.createToken(ts.SyntaxKind.EndOfFileToken); 388 const parent = ts.factory.createSourceFile([], endOfFileToken, ts.NodeFlags.AwaitContext); 389 (node as Mutable<ts.Node>).parent = parent; 390 expect(NodeUtils.getSourceFileOfNode(node)).to.equal(node.parent); 391 }) 392 }) 393 394 describe('test for isDETSFile', function () { 395 it('should return true when node fileName end with .d.ets', function () { 396 const node = ts.factory.createIdentifier('name'); 397 const kind = ts.SyntaxKind.SourceFile; 398 (node as Mutable<ts.Node>).kind = kind; 399 const sourceFile = NodeUtils.getSourceFileOfNode(node); 400 sourceFile.fileName = 'a.d.ets'; 401 expect(NodeUtils.isDETSFile(node)).to.be.true; 402 }) 403 }) 404 405 describe('test for isNewTargetNode', function () { 406 it('should return true when node parent is MetaProperty and node parent keywordToken is yntaxKind.NewKeyword and node escapedText is target', function () { 407 const node = ts.factory.createIdentifier('target'); 408 const parent = ts.factory.createMetaProperty(ts.SyntaxKind.NewKeyword, node); 409 (node as Mutable<ts.Identifier>).parent = parent; 410 expect(NodeUtils.isNewTargetNode(node)).to.be.true; 411 }) 412 it('should return false when node is not a new target node', function () { 413 const node = ts.factory.createIdentifier('name'); 414 const parent = ts.factory.createMetaProperty(ts.SyntaxKind.ImportKeyword, node); 415 (node as Mutable<ts.Identifier>).parent = parent; 416 expect(NodeUtils.isNewTargetNode(node)).to.be.false; 417 }) 418 }) 419 420 describe('test for collectReservedNameForObf', function () { 421 process.env.compileTool = 'rollup'; 422 const ENUM_TEST1: string = 423 'enum ANIMAL {\n' + 424 ' CAT,\n' + 425 ' DOG = CAT + 1,\n' + 426 ' GOOSE = DOG + 1,\n' + 427 ' DUCK = GOOSE + 1,\n' + 428 '}'; 429 it('test1 collectReservedNameForObf-enum: -enable-property-obfuscation, shouldETSOrTSFileTransformToJS = false', function () { 430 const arkConfig = new MergedConfig(); 431 arkConfig.options.enablePropertyObfuscation = true; 432 const result: ts.TranspileOutput = ts.transpileModule(ENUM_TEST1, { 433 compilerOptions: { 434 "target": ts.ScriptTarget.ES2021 435 }, 436 fileName: "enum.ts", 437 transformers: { before: [collectReservedNameForObf(arkConfig, false)] } 438 }); 439 expect(UnobfuscationCollections.reservedEnum.has('CAT')).to.be.true; 440 expect(UnobfuscationCollections.reservedEnum.has('DOG')).to.be.true; 441 expect(UnobfuscationCollections.reservedEnum.has('GOOSE')).to.be.true; 442 expect(UnobfuscationCollections.reservedEnum.has('DUCK')).to.be.false; 443 UnobfuscationCollections.clear(); 444 }) 445 446 const ENUM_TEST2: string = 447 'let test = 1;\n' + 448 'enum ANIMAL {\n' + 449 ' CAT,\n' + 450 ' DOG = (CAT + 1) + test,\n' + 451 '}'; 452 it('test2 collectReservedNameForObf-enum: -enable-property-obfuscation, shouldETSOrTSFileTransformToJS = false', function () { 453 const arkConfig = new MergedConfig(); 454 arkConfig.options.enablePropertyObfuscation = true; 455 const result: ts.TranspileOutput = ts.transpileModule(ENUM_TEST2, { 456 compilerOptions: { 457 "target": ts.ScriptTarget.ES2021 458 }, 459 fileName: "enum.ts", 460 transformers: { before: [collectReservedNameForObf(arkConfig, false)] } 461 }); 462 expect(UnobfuscationCollections.reservedEnum.has('CAT')).to.be.true; 463 expect(UnobfuscationCollections.reservedEnum.has('test')).to.be.true; 464 expect(UnobfuscationCollections.reservedEnum.has('DOG')).to.be.false; 465 UnobfuscationCollections.clear(); 466 }) 467 468 const ENUM_TEST3: string = 469 'class TEST{\n' + 470 ' prop1 = 1\n' + 471 '}\n' + 472 'let myclass = new TEST();\n' + 473 'enum TEST1{\n' + 474 ' AAA,\n' + 475 ' BBB = AAA + myclass.prop1\n' + 476 '}'; 477 it('test3 collectReservedNameForObf-enum: -enable-property-obfuscation, shouldETSOrTSFileTransformToJS = false', function () { 478 const arkConfig = new MergedConfig(); 479 arkConfig.options.enablePropertyObfuscation = true; 480 const result: ts.TranspileOutput = ts.transpileModule(ENUM_TEST3, { 481 compilerOptions: { 482 "target": ts.ScriptTarget.ES2021 483 }, 484 fileName: "enum.ts", 485 transformers: { before: [collectReservedNameForObf(arkConfig, false)] } 486 }); 487 expect(UnobfuscationCollections.reservedEnum.has('AAA')).to.be.true; 488 expect(UnobfuscationCollections.reservedEnum.has('myclass')).to.be.true; 489 expect(UnobfuscationCollections.reservedEnum.has('BBB')).to.be.false; 490 expect(UnobfuscationCollections.reservedEnum.has('prop1')).to.be.false; 491 UnobfuscationCollections.clear(); 492 }) 493 494 it('test4 collectReservedNameForObf-enum: -enable-property-obfuscation, shouldETSOrTSFileTransformToJS = true', function () { 495 const arkConfig = new MergedConfig(); 496 arkConfig.options.enablePropertyObfuscation = true; 497 const result: ts.TranspileOutput = ts.transpileModule(ENUM_TEST3, { 498 compilerOptions: { 499 "target": ts.ScriptTarget.ES2021 500 }, 501 fileName: "enum.js", 502 transformers: { before: [collectReservedNameForObf(arkConfig, true)] } 503 }); 504 expect(UnobfuscationCollections.reservedEnum.size === 0).to.be.true; 505 UnobfuscationCollections.clear(); 506 }) 507 508 const STRUCT_TEST1: string = 509 'class ViewPU {}\n' + 510 'export class Retransmission1 extends ViewPU {\n' + 511 ' constructor() {\n' + 512 ' super();\n' + 513 ' }\n' + 514 ' scroller1: string;\n' + 515 ' controller1: number;\n' + 516 ' callMethod1(): void {};\n' + 517 '}\n' + 518 'class Retransmission2 extends ViewPU {\n' + 519 ' constructor() {\n' + 520 ' super();\n' + 521 ' }\n' + 522 ' scroller2: string;\n' + 523 ' controller2: number;\n' + 524 ' callMethod2(): void {};\n' + 525 '}'; 526 it('test5 collectReservedNameForObf-struct: -enable-property-obfuscation, shouldETSOrTSFileTransformToJS = false', function () { 527 const arkConfig = new MergedConfig(); 528 arkConfig.options.enablePropertyObfuscation = true; 529 const result: ts.TranspileOutput = ts.transpileModule(STRUCT_TEST1, { 530 compilerOptions: { 531 "target": ts.ScriptTarget.ES2021 532 }, 533 fileName: "enum.ts", 534 transformers: { before: [collectReservedNameForObf(arkConfig, false)] } 535 }); 536 expect(UnobfuscationCollections.reservedStruct.has('scroller1')).to.be.true; 537 expect(UnobfuscationCollections.reservedStruct.has('controller1')).to.be.true; 538 expect(UnobfuscationCollections.reservedStruct.has('callMethod1')).to.be.true; 539 expect(UnobfuscationCollections.reservedStruct.has('scroller2')).to.be.true; 540 expect(UnobfuscationCollections.reservedStruct.has('controller2')).to.be.true; 541 expect(UnobfuscationCollections.reservedStruct.has('callMethod2')).to.be.true; 542 UnobfuscationCollections.clear(); 543 }) 544 545 it('test6 collectReservedNameForObf-struct: -disable-obfuscation', function () { 546 const arkConfig = new MergedConfig(); 547 arkConfig.options.disableObfuscation = true; 548 arkConfig.options.enablePropertyObfuscation = true; 549 const result: ts.TranspileOutput = ts.transpileModule(STRUCT_TEST1, { 550 compilerOptions: { 551 "target": ts.ScriptTarget.ES2021 552 }, 553 fileName: "enum.ts", 554 transformers: { before: [collectReservedNameForObf(arkConfig, false)] } 555 }); 556 expect(UnobfuscationCollections.reservedStruct.size === 0).to.be.true; 557 UnobfuscationCollections.clear(); 558 }) 559 }) 560 561 describe('test for hasExportModifier', function () { 562 it('should return false if has no modifier', function () { 563 const fileContent = ` 564 let a = 1; 565 `; 566 const sourceFile: ts.SourceFile = ts.createSourceFile('demo.ts', fileContent, ts.ScriptTarget.ES2015, true); 567 expect(hasExportModifier(sourceFile.statements[0])).to.be.false; 568 }) 569 it('should return false if has no export modifier', function () { 570 const fileContent = ` 571 declare const a = 1; 572 `; 573 const sourceFile: ts.SourceFile = ts.createSourceFile('demo.ts', fileContent, ts.ScriptTarget.ES2015, true); 574 expect(hasExportModifier(sourceFile.statements[0])).to.be.false; 575 }) 576 it('should return true if has export modifier', function () { 577 const fileContent = ` 578 export const a = 1; 579 `; 580 const sourceFile: ts.SourceFile = ts.createSourceFile('demo.ts', fileContent, ts.ScriptTarget.ES2015, true); 581 expect(hasExportModifier(sourceFile.statements[0])).to.be.true; 582 }) 583 }) 584})