浏览代码

Merge pull request #662 from javascript-obfuscator/simplify-and-encoding-fixes

Simplify and encoding fixes
Timofey Kachalov 4 年之前
父节点
当前提交
b2f5a919d3
共有 31 个文件被更改,包括 241 次插入49 次删除
  1. 5 0
      CHANGELOG.md
  2. 0 0
      dist/index.browser.js
  3. 0 0
      dist/index.cli.js
  4. 0 0
      dist/index.js
  5. 1 1
      package.json
  6. 5 0
      src/constants/Base64Alphabet.ts
  7. 8 0
      src/constants/Base64AlphabetSwapped.ts
  8. 1 0
      src/container/ServiceIdentifiers.ts
  9. 7 0
      src/container/modules/utils/UtilsModule.ts
  10. 2 5
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/AtobTemplate.ts
  11. 2 1
      src/interfaces/utils/ICryptUtils.ts
  12. 4 0
      src/interfaces/utils/ICryptUtilsSwappedAlphabet.ts
  13. 17 3
      src/node-transformers/simplifying-transformers/IfStatementSimplifyTransformer.ts
  14. 8 8
      src/storages/string-array/StringArrayStorage.ts
  15. 7 5
      src/utils/CryptUtils.ts
  16. 26 0
      src/utils/CryptUtilsSwappedAlphabet.ts
  17. 8 6
      test/functional-tests/custom-code-helpers/string-array/templates/string-array-calls-wrapper-node-template/StringArrayCallsWrapperNodeTemplate.spec.ts
  18. 62 8
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/IfStatementSimplifyTransformer.spec.ts
  19. 3 0
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/const-variable-declaration-as-prohibited-single-statement.js
  20. 3 0
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/let-variable-declaration-as-prohibited-single-statement.js
  21. 1 1
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-alternate-return-single-statement.js
  22. 1 1
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-consequent-return-single-statement.js
  23. 1 1
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-no-return-mixed-statements-1.js
  24. 1 1
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-no-return-mixed-statements-2.js
  25. 2 2
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-no-return-single-statement.js
  26. 1 1
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-only-no-return-single-statement.js
  27. 3 3
      test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/variable-declarations-merge-transformer-integration-1.js
  28. 1 0
      test/index.spec.ts
  29. 1 1
      test/unit-tests/source-code/ObfuscatedCode.spec.ts
  30. 1 1
      test/unit-tests/utils/CryptUtils.spec.ts
  31. 59 0
      test/unit-tests/utils/CryptUtilsSwappedAlphabet.spec.ts

+ 5 - 0
CHANGELOG.md

@@ -1,5 +1,10 @@
 Change Log
 
+v1.5.1
+---
+* Fixed runtime error when `IfStatement` contains only single `let` or `const` variable declaration when `simlify` option enabled. https://github.com/javascript-obfuscator/javascript-obfuscator/issues/661
+* Fixed wrong `source-map: 'inline'` encoding after `1.3.0`
+
 v1.5.0
 ---
 * New `mangled-shuffled` identifier names generator based on `mangled` identifier names generator

文件差异内容过多而无法显示
+ 0 - 0
dist/index.browser.js


文件差异内容过多而无法显示
+ 0 - 0
dist/index.cli.js


文件差异内容过多而无法显示
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "1.5.0",
+  "version": "1.5.1",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",

+ 5 - 0
src/constants/Base64Alphabet.ts

@@ -0,0 +1,5 @@
+import { alphabetStringUppercase } from './AlphabetStringUppercase';
+import { alphabetString } from './AlphabetString';
+import { numbersString } from './NumbersString';
+
+export const base64alphabet: string = `${alphabetStringUppercase}${alphabetString}${numbersString}+/=`;

+ 8 - 0
src/constants/Base64AlphabetSwapped.ts

@@ -0,0 +1,8 @@
+import { alphabetStringUppercase } from './AlphabetStringUppercase';
+import { alphabetString } from './AlphabetString';
+import { numbersString } from './NumbersString';
+
+/**
+ * Swapped lowercase and uppercase groups of alphabet to prevent easy decode
+ */
+export const base64alphabetSwapped: string = `${alphabetString}${alphabetStringUppercase}${numbersString}+/=`;

+ 1 - 0
src/container/ServiceIdentifiers.ts

@@ -22,6 +22,7 @@ export enum ServiceIdentifiers {
     ICodeTransformerNamesGroupsBuilder = 'ICodeTransformerNamesGroupsBuilder',
     ICodeTransformersRunner = 'ICodeTransformersRunner',
     ICryptUtils = 'ICryptUtils',
+    ICryptUtilsSwappedAlphabet = 'ICryptUtilsSwappedAlphabet',
     ICustomCodeHelper = 'ICustomCodeHelper',
     ICustomCodeHelperGroup = 'ICustomCodeHelperGroup',
     IControlFlowReplacer = 'IControlFlowReplacer',

+ 7 - 0
src/container/modules/utils/UtilsModule.ts

@@ -3,12 +3,14 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 import { IArrayUtils } from '../../../interfaces/utils/IArrayUtils';
 import { ICryptUtils } from '../../../interfaces/utils/ICryptUtils';
+import { ICryptUtilsSwappedAlphabet } from '../../../interfaces/utils/ICryptUtilsSwappedAlphabet';
 import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
 import { ILevelledTopologicalSorter } from '../../../interfaces/utils/ILevelledTopologicalSorter';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 
 import { ArrayUtils } from '../../../utils/ArrayUtils';
 import { CryptUtils } from '../../../utils/CryptUtils';
+import { CryptUtilsSwappedAlphabet } from '../../../utils/CryptUtilsSwappedAlphabet';
 import { EscapeSequenceEncoder } from '../../../utils/EscapeSequenceEncoder';
 import { LevelledTopologicalSorter } from '../../../utils/LevelledTopologicalSorter';
 import { RandomGenerator } from '../../../utils/RandomGenerator';
@@ -29,6 +31,11 @@ export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind
         .to(CryptUtils)
         .inSingletonScope();
 
+    // crypt utils with swapped alphabet
+    bind<ICryptUtilsSwappedAlphabet>(ServiceIdentifiers.ICryptUtilsSwappedAlphabet)
+        .to(CryptUtilsSwappedAlphabet)
+        .inSingletonScope();
+
     // escape sequence encoder
     bind<IEscapeSequenceEncoder>(ServiceIdentifiers.IEscapeSequenceEncoder)
         .to(EscapeSequenceEncoder)

+ 2 - 5
src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/AtobTemplate.ts

@@ -1,15 +1,12 @@
-import { alphabetStringUppercase } from '../../../../constants/AlphabetStringUppercase';
-import { alphabetString } from '../../../../constants/AlphabetString';
-import { numbersString } from '../../../../constants/NumbersString';
+import { base64alphabetSwapped } from '../../../../constants/Base64AlphabetSwapped';
 
 /**
  * @returns {string}
  */
 export function AtobTemplate (): string {
-    // swapped lowercase and uppercase groups of alphabet to prevent easy decode!!!!
     return `
         var {atobFunctionName} = function (input) {
-            const chars = '${alphabetString}${alphabetStringUppercase}${numbersString}+/=';
+            const chars = '${base64alphabetSwapped}';
 
             const str = String(input).replace(/=+$/, '');
             let output = '';

+ 2 - 1
src/interfaces/utils/ICryptUtils.ts

@@ -1,6 +1,7 @@
 export interface ICryptUtils {
     /**
-     * @param string
+     * @param {string} string
+     * @returns {string}
      */
     btoa (string: string): string;
 

+ 4 - 0
src/interfaces/utils/ICryptUtilsSwappedAlphabet.ts

@@ -0,0 +1,4 @@
+/* eslint-disable @typescript-eslint/no-empty-interface */
+import { ICryptUtils } from './ICryptUtils';
+
+export interface ICryptUtilsSwappedAlphabet extends ICryptUtils {}

+ 17 - 3
src/node-transformers/simplifying-transformers/IfStatementSimplifyTransformer.ts

@@ -422,8 +422,9 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
      * @returns {boolean}
      */
     private isProhibitedSingleStatementForIfStatementBranch (statement: ESTree.Statement): boolean {
-        // TODO: write tests
-        // function declaration is not allowed outside of block in `strict` mode
+        /**
+         * Function declaration is not allowed outside of block in `strict` mode
+         */
         return NodeGuards.isFunctionDeclarationNode(statement)
             /**
              * Without ignore it can break following code:
@@ -443,6 +444,19 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
              *     else
              *         var baz = bark();
              */
-            || NodeGuards.isIfStatementNode(statement);
+            || NodeGuards.isIfStatementNode(statement)
+
+            /**
+             * `let` and `const` variable declarations are not allowed outside of `IfStatement` block statement
+             * Input:
+             * if (condition1) {
+             *     const foo = 1;
+             * }
+             *
+             * Invalid output with runtime error:
+             * if (condition1)
+             *     const foo = 1;
+             */
+            || (NodeGuards.isVariableDeclarationNode(statement) && statement.kind !== 'var');
     }
 }

+ 8 - 8
src/storages/string-array/StringArrayStorage.ts

@@ -5,7 +5,7 @@ import { TIdentifierNamesGeneratorFactory } from '../../types/container/generato
 import { IIdentifierNamesGenerator } from '../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
 
 import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
-import { ICryptUtils } from '../../interfaces/utils/ICryptUtils';
+import { ICryptUtilsSwappedAlphabet } from '../../interfaces/utils/ICryptUtilsSwappedAlphabet';
 import { IEncodedValue } from '../../interfaces/IEncodedValue';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
@@ -50,9 +50,9 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
     private readonly arrayUtils: IArrayUtils;
 
     /**
-     * @type {ICryptUtils}
+     * @type {ICryptUtilsSwappedAlphabet}
      */
-    private readonly cryptUtils: ICryptUtils;
+    private readonly cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet;
 
     /**
      * @type {IEscapeSequenceEncoder}
@@ -94,7 +94,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
      * @param {IArrayUtils} arrayUtils
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
-     * @param {ICryptUtils} cryptUtils
+     * @param {ICryptUtilsSwappedAlphabet} cryptUtilsSwappedAlphabet
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      */
     public constructor (
@@ -103,14 +103,14 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
         @inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
-        @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils,
+        @inject(ServiceIdentifiers.ICryptUtilsSwappedAlphabet) cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
         super(randomGenerator, options);
 
         this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
         this.arrayUtils = arrayUtils;
-        this.cryptUtils = cryptUtils;
+        this.cryptUtilsSwappedAlphabet = cryptUtilsSwappedAlphabet;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
 
         this.rc4Keys = this.randomGenerator.getRandomGenerator()
@@ -275,7 +275,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
              */
             case StringArrayEncoding.Rc4: {
                 const decodeKey: string = this.randomGenerator.getRandomGenerator().pickone(this.rc4Keys);
-                const encodedValue: string = this.cryptUtils.btoa(this.cryptUtils.rc4(value, decodeKey));
+                const encodedValue: string = this.cryptUtilsSwappedAlphabet.btoa(this.cryptUtilsSwappedAlphabet.rc4(value, decodeKey));
 
                 const encodedValueSources: string[] = this.rc4EncodedValuesSourcesCache.get(encodedValue) ?? [];
                 let encodedValueSourcesLength: number = encodedValueSources.length;
@@ -298,7 +298,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
 
             case StringArrayEncoding.Base64: {
                 const decodeKey: null = null;
-                const encodedValue: string = this.cryptUtils.btoa(value);
+                const encodedValue: string = this.cryptUtilsSwappedAlphabet.btoa(value);
 
                 return { encodedValue, decodeKey };
             }

+ 7 - 5
src/utils/CryptUtils.ts

@@ -4,15 +4,18 @@ import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 import { ICryptUtils } from '../interfaces/utils/ICryptUtils';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 
-import { alphabetStringUppercase } from '../constants/AlphabetStringUppercase';
-import { alphabetString } from '../constants/AlphabetString';
-import { numbersString } from '../constants/NumbersString';
+import { base64alphabet } from '../constants/Base64Alphabet';
 
 import { RandomGenerator } from './RandomGenerator';
 import { Utils } from './Utils';
 
 @injectable()
 export class CryptUtils implements ICryptUtils {
+    /**
+     * @type {string}
+     */
+    protected readonly base64Alphabet: string = base64alphabet;
+
     /**
      * @type {IRandomGenerator}
      */
@@ -32,8 +35,7 @@ export class CryptUtils implements ICryptUtils {
      * @returns {string}
      */
     public btoa (string: string): string {
-        // swapped lowercase and uppercase groups of alphabet to prevent easy decode!!!!
-        const chars: string = `${alphabetString}${alphabetStringUppercase}${numbersString}+/=`;
+        const chars: string = this.base64Alphabet;
 
         let output: string = '';
 

+ 26 - 0
src/utils/CryptUtilsSwappedAlphabet.ts

@@ -0,0 +1,26 @@
+import { inject, injectable } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import { ICryptUtilsSwappedAlphabet } from '../interfaces/utils/ICryptUtilsSwappedAlphabet';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
+
+import { base64alphabetSwapped } from '../constants/Base64AlphabetSwapped';
+
+import { CryptUtils } from './CryptUtils';
+
+@injectable()
+export class CryptUtilsSwappedAlphabet extends CryptUtils implements ICryptUtilsSwappedAlphabet {
+    /**
+     * @type {string}
+     */
+    protected readonly base64Alphabet: string = base64alphabetSwapped;
+
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        super(randomGenerator);
+    }
+}

+ 8 - 6
test/functional-tests/custom-code-helpers/string-array/templates/string-array-calls-wrapper-node-template/StringArrayCallsWrapperNodeTemplate.spec.ts

@@ -6,7 +6,7 @@ import { assert } from 'chai';
 
 import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
 
-import { ICryptUtils } from '../../../../../../src/interfaces/utils/ICryptUtils';
+import { ICryptUtilsSwappedAlphabet } from '../../../../../../src/interfaces/utils/ICryptUtilsSwappedAlphabet';
 import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
 import { IObfuscatedCode } from '../../../../../../src/interfaces/source-code/IObfuscatedCode';
 import { IRandomGenerator } from '../../../../../../src/interfaces/utils/IRandomGenerator';
@@ -28,15 +28,17 @@ describe('StringArrayCallsWrapperTemplate', () => {
     const stringArrayCallsWrapperName: string = 'stringArrayCallsWrapperName';
     const atobFunctionName: string = 'atob';
 
-    let cryptUtils: ICryptUtils,
+    let cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet,
         randomGenerator: IRandomGenerator;
 
     before(() => {
         const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
 
         inversifyContainerFacade.load('', '', {});
-        cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
-        randomGenerator = inversifyContainerFacade.get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
+        cryptUtilsSwappedAlphabet = inversifyContainerFacade
+            .get<ICryptUtilsSwappedAlphabet>(ServiceIdentifiers.ICryptUtilsSwappedAlphabet);
+        randomGenerator = inversifyContainerFacade
+            .get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
     });
 
     describe('Variant #1: `base64` encoding', () => {
@@ -65,7 +67,7 @@ describe('StringArrayCallsWrapperTemplate', () => {
             });
 
             decodedValue = Function(`
-                var ${stringArrayName} = ['${cryptUtils.btoa('test1')}'];
+                var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa('test1')}'];
             
                 ${stringArrayCallsWrapperTemplate}
                 
@@ -108,7 +110,7 @@ describe('StringArrayCallsWrapperTemplate', () => {
             });
 
             decodedValue = Function(`
-                var ${stringArrayName} = ['${cryptUtils.btoa(cryptUtils.rc4('test1', key))}'];
+                var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'];
             
                 ${stringArrayCallsWrapperTemplate}
                 

+ 62 - 8
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/IfStatementSimplifyTransformer.spec.ts

@@ -353,7 +353,7 @@ describe('IfStatementSimplifyTransformer', () => {
                 describe('Variant #1: single statement', () => {
                     const regExp: RegExp = new RegExp(
                         'if *\\(!!\\[]\\) *' +
-                            'const _0x([a-f0-9]){4,6} *= *baz\\(\\);'
+                            'var _0x([a-f0-9]){4,6} *= *baz\\(\\);'
                     );
 
 
@@ -441,9 +441,9 @@ describe('IfStatementSimplifyTransformer', () => {
                 describe('Variant #1: single statement', () => {
                     const regExp: RegExp = new RegExp(
                         'if *\\(!!\\[]\\) *' +
-                            'const *_0x([a-f0-9]){4,6} *= *baz\\(\\); *' +
+                            'var *_0x([a-f0-9]){4,6} *= *baz\\(\\); *' +
                         'else *' +
-                            'const *_0x([a-f0-9]){4,6} *= *hawk\\(\\);'
+                            'var *_0x([a-f0-9]){4,6} *= *hawk\\(\\);'
                     );
 
 
@@ -501,7 +501,7 @@ describe('IfStatementSimplifyTransformer', () => {
                 describe('Variant #3: mixed statements #1', () => {
                     const regExp: RegExp = new RegExp(
                         'if *\\(!!\\[]\\) *' +
-                            'const *_0x([a-f0-9]){4,6} *= *baz\\(\\); *' +
+                            'var *_0x([a-f0-9]){4,6} *= *baz\\(\\); *' +
                         'else *{ *' +
                             'const *_0x([a-f0-9]){4,6} *= *hawk\\(\\); *' +
                             'eagle\\(\\), *dog\\(\\);' +
@@ -535,7 +535,7 @@ describe('IfStatementSimplifyTransformer', () => {
                                 '_0x([a-f0-9]){4,6} *= *hawk\\(\\); *' +
                             'eagle\\(\\), *pork\\(\\);' +
                         '} *else *' +
-                            'const *_0x([a-f0-9]){4,6} *= *cow\\(\\);'
+                            'var *_0x([a-f0-9]){4,6} *= *cow\\(\\);'
                     );
 
 
@@ -565,7 +565,7 @@ describe('IfStatementSimplifyTransformer', () => {
                         'if *\\(!!\\[]\\) *' +
                             'return *bar\\(\\); *' +
                         'else *' +
-                            'const *_0x([a-f0-9]){4,6} *= *bark\\(\\);'
+                            'var *_0x([a-f0-9]){4,6} *= *bark\\(\\);'
                     );
 
 
@@ -625,7 +625,7 @@ describe('IfStatementSimplifyTransformer', () => {
                 describe('Variant #1: single statement', () => {
                     const regExp: RegExp = new RegExp(
                         'if *\\(!!\\[]\\) *' +
-                            'const *_0x([a-f0-9]){4,6} *= *baz\\(\\); *' +
+                            'var *_0x([a-f0-9]){4,6} *= *baz\\(\\); *' +
                         'else *' +
                             'return *bark\\(\\);'
                     );
@@ -725,7 +725,7 @@ describe('IfStatementSimplifyTransformer', () => {
             describe('Variant #1: three statements', () => {
                 const regExp: RegExp = new RegExp(
                     'if *\\(!!\\[]\\) *' +
-                        'const _0x([a-f0-9]){4,6} *= *function *\\(\\) *{}, *' +
+                        'var _0x([a-f0-9]){4,6} *= *function *\\(\\) *{}, *' +
                             '_0x([a-f0-9]){4,6} *= *function *\\(\\) *{}, *' +
                             '_0x([a-f0-9]){4,6} *= *function *\\(\\) *{};'
                 );
@@ -809,6 +809,60 @@ describe('IfStatementSimplifyTransformer', () => {
                     assert.match(obfuscatedCode, regExp);
                 });
             });
+
+            describe('Variant #3: `let` `VariableDeclaration` as prohibited single statement', () => {
+                const regExp: RegExp = new RegExp(
+                    'if *\\(!!\\[]\\) *{ *' +
+                        'let foo *= *0x1; *' +
+                    '}'
+                );
+
+
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/let-variable-declaration-as-prohibited-single-statement.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            simplify: true
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should not simplify if statement', () => {
+                    assert.match(obfuscatedCode, regExp);
+                });
+            });
+
+            describe('Variant #4: `const` `VariableDeclaration` as prohibited single statement', () => {
+                const regExp: RegExp = new RegExp(
+                    'if *\\(!!\\[]\\) *{ *' +
+                        'const foo *= *0x1; *' +
+                    '}'
+                );
+
+
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/const-variable-declaration-as-prohibited-single-statement.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            simplify: true
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should not simplify if statement', () => {
+                    assert.match(obfuscatedCode, regExp);
+                });
+            });
         });
     });
 });

+ 3 - 0
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/const-variable-declaration-as-prohibited-single-statement.js

@@ -0,0 +1,3 @@
+if (true) {
+    const foo = 1;
+}

+ 3 - 0
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/let-variable-declaration-as-prohibited-single-statement.js

@@ -0,0 +1,3 @@
+if (true) {
+    let foo = 1;
+}

+ 1 - 1
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-alternate-return-single-statement.js

@@ -1,6 +1,6 @@
 function foo () {
     if (true) {
-        const bar = baz();
+        var bar = baz();
     } else {
         return bark();
     }

+ 1 - 1
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-consequent-return-single-statement.js

@@ -2,6 +2,6 @@ function foo () {
     if (true) {
         return bar();
     } else {
-        const baz = bark();
+        var baz = bark();
     }
 }

+ 1 - 1
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-no-return-mixed-statements-1.js

@@ -1,6 +1,6 @@
 function foo () {
     if (true) {
-        const bar = baz();
+        var bar = baz();
     } else {
         const bark = hawk();
 

+ 1 - 1
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-no-return-mixed-statements-2.js

@@ -6,6 +6,6 @@ function foo () {
         eagle()
         pork();
     } else {
-        const horse = cow();
+        var horse = cow();
     }
 }

+ 2 - 2
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-and-alternate-no-return-single-statement.js

@@ -1,7 +1,7 @@
 function foo () {
     if (true) {
-        const bar = baz();
+        var bar = baz();
     } else {
-        const bark = hawk();
+        var bark = hawk();
     }
 }

+ 1 - 1
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/partial-consequent-only-no-return-single-statement.js

@@ -1,5 +1,5 @@
 function foo () {
     if (true) {
-        const bar = baz();
+        var bar = baz();
     }
 }

+ 3 - 3
test/functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/fixtures/variable-declarations-merge-transformer-integration-1.js

@@ -1,7 +1,7 @@
 function foo() {
     if (true) {
-        const bar = function () {};
-        const baz = function () {};
-        const bark = function () {};
+        var bar = function () {};
+        var baz = function () {};
+        var bark = function () {};
     }
 }

+ 1 - 0
test/index.spec.ts

@@ -44,6 +44,7 @@ import './unit-tests/storages/MapStorage.spec';
 import './unit-tests/storages/string-array/StringArrayStorage.spec';
 import './unit-tests/utils/ArrayUtils.spec';
 import './unit-tests/utils/CryptUtils.spec';
+import './unit-tests/utils/CryptUtilsSwappedAlphabet.spec';
 import './unit-tests/utils/EscapeSequenceEncoder.spec';
 import './unit-tests/utils/LevelledTopologicalSorter.spec';
 import './unit-tests/utils/NumberUtils.spec';

+ 1 - 1
test/unit-tests/source-code/ObfuscatedCode.spec.ts

@@ -89,7 +89,7 @@ describe('ObfuscatedCode', () => {
         });
 
         describe('source map is set, source map mode is `inline`', () => {
-            const regExp: RegExp = /data:application\/json;base64/;
+            const regExp: RegExp = /data:application\/json;base64,dGVzdA==/;
 
             before(() => {
                 obfuscatedCode = getObfuscatedCode(

+ 1 - 1
test/unit-tests/utils/CryptUtils.spec.ts

@@ -22,7 +22,7 @@ describe('CryptUtils', () => {
     });
 
     describe('btoa', () => {
-        const expectedString: string = swapLettersCase('c3RyaW5n');
+        const expectedString: string = swapLettersCase('C3rYAw5N');
 
         let string: string;
 

+ 59 - 0
test/unit-tests/utils/CryptUtilsSwappedAlphabet.spec.ts

@@ -0,0 +1,59 @@
+import 'reflect-metadata';
+
+import { assert } from 'chai';
+
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { ICryptUtilsSwappedAlphabet } from '../../../src/interfaces/utils/ICryptUtilsSwappedAlphabet';
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
+
+import { swapLettersCase } from '../../helpers/swapLettersCase';
+
+describe('CryptUtilsSwappedAlphabet', () => {
+    let cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet;
+
+    before(() => {
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load('', '', {});
+        cryptUtilsSwappedAlphabet = inversifyContainerFacade
+            .get<ICryptUtilsSwappedAlphabet>(ServiceIdentifiers.ICryptUtilsSwappedAlphabet);
+    });
+
+    describe('btoa', () => {
+        const expectedString: string = swapLettersCase('c3RyaW5n');
+
+        let string: string;
+
+        before(() => {
+            string = cryptUtilsSwappedAlphabet.btoa('string');
+        });
+
+        it('should create a base-64 encoded string with swapped alphabet from a given string', () => {
+            assert.equal(string, expectedString);
+        });
+    });
+
+    describe('rc4', () => {
+        const string: string = 'test';
+        const key: string = 'key';
+
+        let encodedString: string,
+            decodedString: string;
+
+        before(() => {
+            encodedString = cryptUtilsSwappedAlphabet.rc4(string, key);
+            decodedString = cryptUtilsSwappedAlphabet.rc4(encodedString, key);
+        });
+
+        it('should encode string using the rc4 algorithm', () => {
+            assert.notEqual(encodedString, string);
+        });
+
+        it('should encode and successfully decode string using the rc4 algorithm', () => {
+            assert.equal(decodedString, string);
+        });
+    });
+});

部分文件因为文件数量过多而无法显示