Prechádzať zdrojové kódy

Merge pull request #466 from javascript-obfuscator/custom-nodes-identifier-names-collision-fix

Custom nodes identifier names collision fix
Timofey Kachalov 5 rokov pred
rodič
commit
248f6348e3
29 zmenil súbory, kde vykonal 357 pridanie a 150 odobranie
  1. 6 0
      CHANGELOG.md
  2. 2 2
      README.md
  3. 0 0
      dist/index.browser.js
  4. 0 0
      dist/index.cli.js
  5. 0 0
      dist/index.js
  6. 1 1
      package.json
  7. 1 1
      src/JavaScriptObfuscator.ts
  8. 1 1
      src/cli/JavaScriptObfuscatorCLI.ts
  9. 41 40
      src/container/modules/generators/GeneratorsModule.ts
  10. 1 1
      src/container/modules/node-transformers/PreparingTransformersModule.ts
  11. 1 1
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  12. 1 1
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  13. 1 1
      src/interfaces/options/IOptions.d.ts
  14. 7 2
      src/interfaces/utils/IRandomGenerator.d.ts
  15. 0 0
      src/node-transformers/preparing-transformers/EvalCallExpressionTransformer.ts
  16. 2 3
      src/options/Options.ts
  17. 2 0
      src/options/OptionsNormalizer.ts
  18. 25 0
      src/options/normalizer-rules/SeedRule.ts
  19. 0 4
      src/storages/string-array/StringArrayStorage.ts
  20. 1 1
      src/templates/debug-protection-nodes/debug-protection-function-call-node/DebugProtectionFunctionCallTemplate.ts
  21. 22 26
      src/utils/RandomGenerator.ts
  22. 38 7
      test/dev/dev.ts
  23. 43 2
      test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts
  24. 4 0
      test/functional-tests/javascript-obfuscator/fixtures/custom-nodes-identifier-names-collision.js
  25. 2 2
      test/functional-tests/node-transformers/obfuscating-transformers/class-declaration-transformer/ClassDeclarationTransformer.spec.ts
  26. 2 2
      test/functional-tests/node-transformers/obfuscating-transformers/function-declaration-transformer/FunctionDeclarationTransformer.spec.ts
  27. 9 9
      test/functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts
  28. 99 36
      test/functional-tests/options/OptionsNormalizer.spec.ts
  29. 45 7
      test/functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec.ts

+ 6 - 0
CHANGELOG.md

@@ -1,5 +1,11 @@
 Change Log
 Change Log
 
 
+v0.20.1
+---
+* Fixed identifier names generations for `mangled` and `dictionary` identifier names generators
+* Fixed combination of `identifierNamesGenerator: dictionary` and `debugProtection` options
+* `seed` option now accepts `string` and `number` values
+
 v0.20.0
 v0.20.0
 ---
 ---
 * **Breaking:** dropped support of Node 8 because of end of maintenance support
 * **Breaking:** dropped support of Node 8 because of end of maintenance support

+ 2 - 2
README.md

@@ -343,7 +343,7 @@ Following options are available for the JS Obfuscator:
     --reserved-names '<list>' (comma separated)
     --reserved-names '<list>' (comma separated)
     --reserved-strings '<list>' (comma separated)
     --reserved-strings '<list>' (comma separated)
     --rotate-string-array <boolean>
     --rotate-string-array <boolean>
-    --seed <number>
+    --seed <string|number>
     --self-defending <boolean>
     --self-defending <boolean>
     --source-map <boolean>
     --source-map <boolean>
     --source-map-base-url <string>
     --source-map-base-url <string>
@@ -673,7 +673,7 @@ Shift the `stringArray` array by a fixed and random (generated at the code obfus
 This option is recommended if your original source code isn't small, as the helper function can attract attention.
 This option is recommended if your original source code isn't small, as the helper function can attract attention.
 
 
 ### `seed`
 ### `seed`
-Type: `number` Default: `0`
+Type: `string|number` Default: `0`
 
 
 This option sets seed for random generator. This is useful for creating repeatable results.
 This option sets seed for random generator. This is useful for creating repeatable results.
 
 

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
dist/index.browser.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
dist/index.cli.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

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

+ 1 - 1
src/JavaScriptObfuscator.ts

@@ -127,7 +127,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
         const timeStart: number = Date.now();
         const timeStart: number = Date.now();
         this.logger.info(LoggingMessage.Version, process.env.VERSION);
         this.logger.info(LoggingMessage.Version, process.env.VERSION);
         this.logger.info(LoggingMessage.ObfuscationStarted);
         this.logger.info(LoggingMessage.ObfuscationStarted);
-        this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getSeed());
+        this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getInputSeed());
 
 
         // parse AST tree
         // parse AST tree
         const astTree: ESTree.Program = this.parseCode(sourceCode);
         const astTree: ESTree.Program = this.parseCode(sourceCode);

+ 1 - 1
src/cli/JavaScriptObfuscatorCLI.ts

@@ -287,7 +287,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
                 BooleanSanitizer
                 BooleanSanitizer
             )
             )
             .option(
             .option(
-                '--seed <number>',
+                '--seed <string|number>',
                 'Sets seed for random generator. This is useful for creating repeatable results.',
                 'Sets seed for random generator. This is useful for creating repeatable results.',
                 parseFloat
                 parseFloat
             )
             )

+ 41 - 40
src/container/modules/generators/GeneratorsModule.ts

@@ -28,45 +28,46 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
         .whenTargetNamed(IdentifierNamesGenerator.MangledIdentifierNamesGenerator);
         .whenTargetNamed(IdentifierNamesGenerator.MangledIdentifierNamesGenerator);
 
 
     // identifier name generator factory
     // identifier name generator factory
+    function identifierNameGeneratorFactory (): (context: interfaces.Context) => (options: IOptions) => IIdentifierNamesGenerator {
+        let cachedIdentifierNamesGenerator: IIdentifierNamesGenerator | null = null;
+
+        return (context: interfaces.Context): (options: IOptions) => IIdentifierNamesGenerator => (options: IOptions) => {
+            if (cachedIdentifierNamesGenerator) {
+                return cachedIdentifierNamesGenerator;
+            }
+
+            let identifierNamesGenerator: IIdentifierNamesGenerator;
+
+            switch (options.identifierNamesGenerator) {
+                case IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator:
+                    identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
+                        ServiceIdentifiers.IIdentifierNamesGenerator,
+                        IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
+                    );
+
+                    break;
+
+                case IdentifierNamesGenerator.MangledIdentifierNamesGenerator:
+                    identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
+                        ServiceIdentifiers.IIdentifierNamesGenerator,
+                        IdentifierNamesGenerator.MangledIdentifierNamesGenerator
+                    );
+
+                    break;
+
+                case IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator:
+                default:
+                    identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
+                        ServiceIdentifiers.IIdentifierNamesGenerator,
+                        IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
+                    );
+            }
+
+            cachedIdentifierNamesGenerator = identifierNamesGenerator;
+
+            return identifierNamesGenerator;
+        };
+    }
     bind<IIdentifierNamesGenerator>(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
     bind<IIdentifierNamesGenerator>(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-        .toFactory<IIdentifierNamesGenerator>((context: interfaces.Context): (options: IOptions) => IIdentifierNamesGenerator => {
-            let cachedIdentifierNamesGenerator: IIdentifierNamesGenerator | null = null;
-
-            return (options: IOptions) => {
-                if (cachedIdentifierNamesGenerator) {
-                    return cachedIdentifierNamesGenerator;
-                }
-
-                let identifierNamesGenerator: IIdentifierNamesGenerator;
-
-                switch (options.identifierNamesGenerator) {
-                    case IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator:
-                        identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
-                            ServiceIdentifiers.IIdentifierNamesGenerator,
-                            IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
-                        );
-
-                        break;
-
-                    case IdentifierNamesGenerator.MangledIdentifierNamesGenerator:
-                        identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
-                            ServiceIdentifiers.IIdentifierNamesGenerator,
-                            IdentifierNamesGenerator.MangledIdentifierNamesGenerator
-                        );
-
-                        break;
-
-                    case IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator:
-                    default:
-                        identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
-                            ServiceIdentifiers.IIdentifierNamesGenerator,
-                            IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
-                        );
-                }
-
-                cachedIdentifierNamesGenerator = identifierNamesGenerator;
-
-                return identifierNamesGenerator;
-            };
-        });
+        .toFactory<IIdentifierNamesGenerator>(identifierNameGeneratorFactory());
 });
 });

+ 1 - 1
src/container/modules/node-transformers/PreparingTransformersModule.ts

@@ -12,7 +12,7 @@ import { BlackListObfuscatingGuard } from '../../../node-transformers/preparing-
 import { CommentsTransformer } from '../../../node-transformers/preparing-transformers/CommentsTransformer';
 import { CommentsTransformer } from '../../../node-transformers/preparing-transformers/CommentsTransformer';
 import { ConditionalCommentObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ConditionalCommentObfuscatingGuard';
 import { ConditionalCommentObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ConditionalCommentObfuscatingGuard';
 import { CustomNodesTransformer } from '../../../node-transformers/preparing-transformers/CustomNodesTransformer';
 import { CustomNodesTransformer } from '../../../node-transformers/preparing-transformers/CustomNodesTransformer';
-import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvaCallExpressionTransformer';
+import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvalCallExpressionTransformer';
 import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer';
 import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer';
 import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer';
 import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer';
 import { ParentificationTransformer } from '../../../node-transformers/preparing-transformers/ParentificationTransformer';
 import { ParentificationTransformer } from '../../../node-transformers/preparing-transformers/ParentificationTransformer';

+ 1 - 1
src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts

@@ -101,7 +101,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
                 ...NO_ADDITIONAL_NODES_PRESET,
                 ...NO_ADDITIONAL_NODES_PRESET,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 identifiersDictionary: this.options.identifiersDictionary,
                 identifiersDictionary: this.options.identifiersDictionary,
-                seed: this.options.seed
+                seed: this.randomGenerator.getRawSeed()
             }
             }
         ).getObfuscatedCode();
         ).getObfuscatedCode();
     }
     }

+ 1 - 1
src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts

@@ -108,7 +108,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
                 ...NO_ADDITIONAL_NODES_PRESET,
                 ...NO_ADDITIONAL_NODES_PRESET,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 identifiersDictionary: this.options.identifiersDictionary,
                 identifiersDictionary: this.options.identifiersDictionary,
-                seed: this.options.seed
+                seed: this.randomGenerator.getRawSeed()
             }
             }
         ).getObfuscatedCode();
         ).getObfuscatedCode();
     }
     }

+ 1 - 1
src/interfaces/options/IOptions.d.ts

@@ -23,7 +23,7 @@ export interface IOptions {
     readonly reservedNames: string[];
     readonly reservedNames: string[];
     readonly reservedStrings: string[];
     readonly reservedStrings: string[];
     readonly rotateStringArray: boolean;
     readonly rotateStringArray: boolean;
-    readonly seed: number;
+    readonly seed: string | number;
     readonly selfDefending: boolean;
     readonly selfDefending: boolean;
     readonly sourceMap: boolean;
     readonly sourceMap: boolean;
     readonly sourceMapBaseUrl: string;
     readonly sourceMapBaseUrl: string;

+ 7 - 2
src/interfaces/utils/IRandomGenerator.d.ts

@@ -26,7 +26,12 @@ export interface IRandomGenerator {
     getRandomString (length: number, pool?: string): string;
     getRandomString (length: number, pool?: string): string;
 
 
     /**
     /**
-     * @returns {number}
+     * @returns {string}
+     */
+    getInputSeed (): string;
+
+    /**
+     * @returns {string}
      */
      */
-    getSeed (): number;
+    getRawSeed (): string;
 }
 }

+ 0 - 0
src/node-transformers/preparing-transformers/EvaCallExpressionTransformer.ts → src/node-transformers/preparing-transformers/EvalCallExpressionTransformer.ts


+ 2 - 3
src/options/Options.ts

@@ -176,10 +176,9 @@ export class Options implements IOptions {
     public readonly rotateStringArray!: boolean;
     public readonly rotateStringArray!: boolean;
 
 
     /**
     /**
-     * @type {number}
+     * @type {string | number}
      */
      */
-    @IsNumber()
-    public readonly seed!: number;
+    public readonly seed!: string | number;
 
 
     /**
     /**
      * @type {boolean}
      * @type {boolean}

+ 2 - 0
src/options/OptionsNormalizer.ts

@@ -10,6 +10,7 @@ import { DeadCodeInjectionRule } from './normalizer-rules/DeadCodeInjectionRule'
 import { DeadCodeInjectionThresholdRule } from './normalizer-rules/DeadCodeInjectionThresholdRule';
 import { DeadCodeInjectionThresholdRule } from './normalizer-rules/DeadCodeInjectionThresholdRule';
 import { DomainLockRule } from './normalizer-rules/DomainLockRule';
 import { DomainLockRule } from './normalizer-rules/DomainLockRule';
 import { InputFileNameRule } from './normalizer-rules/InputFileNameRule';
 import { InputFileNameRule } from './normalizer-rules/InputFileNameRule';
+import { SeedRule } from './normalizer-rules/SeedRule';
 import { SelfDefendingRule } from './normalizer-rules/SelfDefendingRule';
 import { SelfDefendingRule } from './normalizer-rules/SelfDefendingRule';
 import { SourceMapBaseUrlRule } from './normalizer-rules/SourceMapBaseUrlRule';
 import { SourceMapBaseUrlRule } from './normalizer-rules/SourceMapBaseUrlRule';
 import { SourceMapFileNameRule } from './normalizer-rules/SourceMapFileNameRule';
 import { SourceMapFileNameRule } from './normalizer-rules/SourceMapFileNameRule';
@@ -29,6 +30,7 @@ export class OptionsNormalizer implements IOptionsNormalizer {
         DeadCodeInjectionThresholdRule,
         DeadCodeInjectionThresholdRule,
         DomainLockRule,
         DomainLockRule,
         InputFileNameRule,
         InputFileNameRule,
+        SeedRule,
         SelfDefendingRule,
         SelfDefendingRule,
         SourceMapBaseUrlRule,
         SourceMapBaseUrlRule,
         SourceMapFileNameRule,
         SourceMapFileNameRule,

+ 25 - 0
src/options/normalizer-rules/SeedRule.ts

@@ -0,0 +1,25 @@
+import { TOptionsNormalizerRule } from '../../types/options/TOptionsNormalizerRule';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+
+/**
+ * @param {IOptions} options
+ * @returns {IOptions}
+ */
+export const SeedRule: TOptionsNormalizerRule = (options: IOptions): IOptions => {
+    if (options.seed) {
+        return {
+            ...options,
+            seed: options.seed
+        };
+    }
+
+    const getRandomInteger: (min: number, max: number) => number = (min: number, max: number) => {
+        return Math.floor(Math.random() * (max - min + 1) + min);
+    };
+
+    return {
+        ...options,
+        seed: getRandomInteger(0, 999_999_999)
+    };
+};

+ 0 - 4
src/storages/string-array/StringArrayStorage.ts

@@ -50,10 +50,6 @@ export class StringArrayStorage extends ArrayStorage <string> {
     public initialize (): void {
     public initialize (): void {
         super.initialize();
         super.initialize();
 
 
-        if (!this.options.stringArray) {
-            return;
-        }
-
         const baseStringArrayName: string = this.identifierNamesGenerator
         const baseStringArrayName: string = this.identifierNamesGenerator
             .generate(StringArrayStorage.stringArrayNameLength);
             .generate(StringArrayStorage.stringArrayNameLength);
         const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator
         const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator

+ 1 - 1
src/templates/debug-protection-nodes/debug-protection-function-call-node/DebugProtectionFunctionCallTemplate.ts

@@ -6,7 +6,7 @@ export function DebugProtectionFunctionCallTemplate (): string {
         (function () {
         (function () {
             {singleNodeCallControllerFunctionName}(this, function () {
             {singleNodeCallControllerFunctionName}(this, function () {
                 var regExp1 = new RegExp('function *\\\\( *\\\\)');
                 var regExp1 = new RegExp('function *\\\\( *\\\\)');
-                var regExp2 = new RegExp('\\\\+\\\\+ *\\(?:_0x(?:[a-f0-9]){4,6}|(?:\\\\b|\\\\d)[a-z0-9]{1,4}(?:\\\\b|\\\\d)\\)', 'i');
+                var regExp2 = new RegExp('\\\\+\\\\+ *\\(?:[a-zA-Z_$][0-9a-zA-Z_$]*\\)', 'i');
        
        
                 var result = {debugProtectionFunctionName}('init');
                 var result = {debugProtectionFunctionName}('init');
                 
                 

+ 22 - 26
src/utils/RandomGenerator.ts

@@ -29,12 +29,6 @@ export class RandomGenerator implements IRandomGenerator, IInitializable {
     @initializable()
     @initializable()
     private randomGenerator!: Chance.Chance;
     private randomGenerator!: Chance.Chance;
 
 
-    /**
-     * @type {number}
-     */
-    @initializable()
-    private seed!: number;
-
     /**
     /**
      * @type {ISourceCode}
      * @type {ISourceCode}
      */
      */
@@ -54,24 +48,7 @@ export class RandomGenerator implements IRandomGenerator, IInitializable {
 
 
     @postConstruct()
     @postConstruct()
     public initialize (): void {
     public initialize (): void {
-        const getRandomInteger: (min: number, max: number) => number = (min: number, max: number) => {
-            return Math.floor(Math.random() * (max - min + 1) + min);
-        };
-
-        /**
-         * We need to add numbers from md5 hash of source code to input seed to prevent same String Array name
-         * for different bundles with same seed
-         *
-         * @returns {number}
-         */
-        const getSeed: () => number = (): number => {
-            const md5Hash: string = md5(this.sourceCode.getSourceCode());
-
-            return this.seed + Number(md5Hash.replace(/\D/g, ''));
-        };
-
-        this.seed = this.options.seed !== 0 ? this.options.seed : getRandomInteger(0, 999_999_999);
-        this.randomGenerator = new Chance(getSeed());
+        this.randomGenerator = new Chance(this.getRawSeed());
     }
     }
 
 
     /**
     /**
@@ -110,9 +87,28 @@ export class RandomGenerator implements IRandomGenerator, IInitializable {
     }
     }
 
 
     /**
     /**
+     * @returns {string}
+     */
+    public getInputSeed (): string {
+        return this.options.seed.toString();
+    }
+
+    /**
+     * We need to add numbers from md5 hash of source code to input seed to prevent same String Array name
+     * for different bundles with same seed
+     *
      * @returns {number}
      * @returns {number}
      */
      */
-    public getSeed (): number {
-        return this.seed;
+    public getRawSeed (): string {
+        const inputSeed: string = this.getInputSeed();
+        const inputSeedParts: string[] = `${inputSeed}`.split('|');
+
+        if (inputSeedParts.length > 1) {
+            return inputSeed;
+        }
+
+        const sourceCodeMD5Hash: string = md5(this.sourceCode.getSourceCode());
+
+        return `${inputSeed}|${sourceCodeMD5Hash}`;
     }
     }
 }
 }

+ 38 - 7
test/dev/dev.ts

@@ -1,20 +1,51 @@
 'use strict';
 'use strict';
-import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
+import { IdentifierNamesGenerator } from '../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
 
 
 (function () {
 (function () {
     const JavaScriptObfuscator: any = require('../../index');
     const JavaScriptObfuscator: any = require('../../index');
 
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
         `
-            var abc = 1;
-            var cde = 1;
-            var fg = 1;
-            var sss = 1;
+            // Paste your JavaScript code here
+            function hi() {
+              console.log("Hello World!");
+            }
+            hi();
         `,
         `,
         {
         {
-            ...NO_ADDITIONAL_NODES_PRESET,
             compact: false,
             compact: false,
-            renameGlobals: true
+            selfDefending: false,
+            disableConsoleOutput: false,
+            debugProtection: false,
+            debugProtectionInterval: false,
+            splitStrings: true,
+            splitStringsChunkLength: 5,
+            splitStringsChunkLengthEnabled: true,
+            stringArray: true,
+            rotateStringArray: false,
+            rotateStringArrayEnabled: true,
+            stringArrayThreshold: 1,
+            stringArrayThresholdEnabled: true,
+            stringArrayEncoding: false,
+            stringArrayEncodingEnabled: true,
+            sourceMap: false,
+            sourceMapBaseUrl: "",
+            sourceMapFileName: "",
+            sourceMapSeparate: false,
+            domainLock: [],
+            reservedNames: [],
+            reservedStrings: [],
+            seed: 0,
+            controlFlowFlatteningThreshold: 1,
+            controlFlowFlattening: true,
+            deadCodeInjectionThreshold: 1,
+            deadCodeInjection: true,
+            unicodeEscapeSequence: false,
+            renameGlobals: true,
+            identifierNamesGenerator: IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
+            identifiersDictionary: ["foo", "bar", "baz", "bark", "hawk", "fooz", "moscow", "chikago"],
+            identifiersPrefix: "",
+            transformObjectKeys: true
         }
         }
     ).getObfuscatedCode();
     ).getObfuscatedCode();
 
 

+ 43 - 2
test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts

@@ -570,7 +570,7 @@ describe('JavaScriptObfuscator', () => {
         });
         });
 
 
         describe('dictionary identifier names generator', () => {
         describe('dictionary identifier names generator', () => {
-            const regExp: RegExp = /var *[ab] *= *0x1; *var *[ab] *= *0x2; *var *[AB] *= *0x3;/;
+            const regExp: RegExp = /var *[abc] *= *0x1; *var *[ABC] *= *0x2; *var *[ABC] *= *0x3;/;
 
 
             let obfuscatedCode: string;
             let obfuscatedCode: string;
 
 
@@ -582,7 +582,7 @@ describe('JavaScriptObfuscator', () => {
                     {
                     {
                         ...NO_ADDITIONAL_NODES_PRESET,
                         ...NO_ADDITIONAL_NODES_PRESET,
                         identifierNamesGenerator: IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
                         identifierNamesGenerator: IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
-                        identifiersDictionary: ['a', 'b']
+                        identifiersDictionary: ['a', 'b', 'c']
                     }
                     }
                 ).getObfuscatedCode();
                 ).getObfuscatedCode();
             });
             });
@@ -666,5 +666,46 @@ describe('JavaScriptObfuscator', () => {
                 assert.equal(result, expectedValue);
                 assert.equal(result, expectedValue);
             });
             });
         });
         });
+
+        describe('Identifier names collision between base code and appended string array nodes', () => {
+            const samplesCount: number = 30;
+
+            let areCollisionsExists: boolean = false;
+            let obfuscateFunc: (identifierNamesGenerator: IdentifierNamesGenerator) => string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/custom-nodes-identifier-names-collision.js');
+
+                obfuscateFunc = (identifierNamesGenerator: IdentifierNamesGenerator) => JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        identifierNamesGenerator,
+                        compact: false,
+                        renameGlobals: true,
+                        identifiersDictionary: ['foo', 'bar', 'baz', 'bark', 'hawk', 'foozmos', 'cow', 'chikago'],
+                        stringArray: true
+                    }
+                ).getObfuscatedCode();
+
+
+                [
+                    IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
+                    IdentifierNamesGenerator.MangledIdentifierNamesGenerator
+                ].forEach((identifierNamesGenerator: IdentifierNamesGenerator) => {
+                    for (let i = 0; i < samplesCount; i++) {
+                        try {
+                            eval(obfuscateFunc(identifierNamesGenerator));
+                        } catch {
+                            areCollisionsExists = true;
+                            break;
+                        }
+                    }
+                });
+            });
+
+            it('It does not create identifier names collision', () => {
+                assert.equal(areCollisionsExists, false);
+            });
+        });
     });
     });
 });
 });

+ 4 - 0
test/functional-tests/javascript-obfuscator/fixtures/custom-nodes-identifier-names-collision.js

@@ -0,0 +1,4 @@
+function hi() {
+    console.log("Hello World!");
+}
+hi();

+ 2 - 2
test/functional-tests/node-transformers/obfuscating-transformers/class-declaration-transformer/ClassDeclarationTransformer.spec.ts

@@ -121,8 +121,8 @@ describe('ClassDeclarationTransformer', () => {
         });
         });
 
 
         describe('Variant #3: already renamed identifiers shouldn\'t be renamed twice', () => {
         describe('Variant #3: already renamed identifiers shouldn\'t be renamed twice', () => {
-            const classDeclarationRegExp: RegExp = /class *b *{/;
-            const variableDeclarationsRegExp: RegExp = /let *c, *d, *e, *f;/;
+            const classDeclarationRegExp: RegExp = /class *d *{/;
+            const variableDeclarationsRegExp: RegExp = /let *e, *f, *g, *h;/;
 
 
             let obfuscatedCode: string;
             let obfuscatedCode: string;
 
 

+ 2 - 2
test/functional-tests/node-transformers/obfuscating-transformers/function-declaration-transformer/FunctionDeclarationTransformer.spec.ts

@@ -145,8 +145,8 @@ describe('FunctionDeclarationTransformer', () => {
 
 
         describe('Variant #5: already renamed identifiers shouldn\'t be renamed twice', () => {
         describe('Variant #5: already renamed identifiers shouldn\'t be renamed twice', () => {
             describe('Variant #1', () => {
             describe('Variant #1', () => {
-                const functionDeclarationRegExp: RegExp = /function *b\(\) *{/;
-                const variableDeclarationsRegExp: RegExp = /let *c, *d, *e, *f;/;
+                const functionDeclarationRegExp: RegExp = /function *d\(\) *{/;
+                const variableDeclarationsRegExp: RegExp = /let *e, *f, *g, *h;/;
 
 
                 let obfuscatedCode: string;
                 let obfuscatedCode: string;
 
 

+ 9 - 9
test/functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts

@@ -426,11 +426,11 @@ describe('VariableDeclarationTransformer', () => {
 
 
     describe('Variant #13: already renamed identifiers shouldn\'t be renamed twice', () => {
     describe('Variant #13: already renamed identifiers shouldn\'t be renamed twice', () => {
         describe('Variant #1', () => {
         describe('Variant #1', () => {
-            const variableDeclarationRegExp: RegExp = /var *b *= *0x1;/;
-            const functionDeclarationRegExp1: RegExp = /function *c *\(\) *{}/;
-            const functionDeclarationRegExp2: RegExp = /function *d *\(\) *{}/;
-            const functionDeclarationRegExp3: RegExp = /function *e *\(\) *{}/;
-            const functionDeclarationRegExp4: RegExp = /function *f *\(\) *{}/;
+            const variableDeclarationRegExp: RegExp = /var *d *= *0x1;/;
+            const functionDeclarationRegExp1: RegExp = /function *e *\(\) *{}/;
+            const functionDeclarationRegExp2: RegExp = /function *f *\(\) *{}/;
+            const functionDeclarationRegExp3: RegExp = /function *g *\(\) *{}/;
+            const functionDeclarationRegExp4: RegExp = /function *h *\(\) *{}/;
 
 
             let obfuscatedCode: string;
             let obfuscatedCode: string;
 
 
@@ -468,10 +468,10 @@ describe('VariableDeclarationTransformer', () => {
         });
         });
 
 
         describe('Variant #2', () => {
         describe('Variant #2', () => {
-            const variableDeclarationRegExp1: RegExp = /var *b *= *0x1;/;
-            const variableDeclarationRegExp2: RegExp = /var *c;/;
-            const functionDeclarationRegExp: RegExp = /function *d *\(\) *{/;
-            const variableDeclarationRegExp3: RegExp = /var *d *= *function *\(\) *{}/;
+            const variableDeclarationRegExp1: RegExp = /var *d *= *0x1;/;
+            const variableDeclarationRegExp2: RegExp = /var *e;/;
+            const functionDeclarationRegExp: RegExp = /function *f *\(\) *{/;
+            const variableDeclarationRegExp3: RegExp = /var *f *= *function *\(\) *{}/;
 
 
             let obfuscatedCode: string;
             let obfuscatedCode: string;
 
 

+ 99 - 36
test/functional-tests/options/OptionsNormalizer.spec.ts

@@ -33,6 +33,13 @@ function getNormalizedOptions (optionsPreset: TInputOptions): TInputOptions {
     return <TInputOptions>optionsNormalizer.normalize(options);
     return <TInputOptions>optionsNormalizer.normalize(options);
 }
 }
 
 
+function getDefaultOptions(): TInputOptions {
+    return {
+        ...DEFAULT_PRESET,
+        seed: 1 // set `seed` to the fixed value, to prevent a new seed for the each case
+    };
+}
+
 describe('OptionsNormalizer', () => {
 describe('OptionsNormalizer', () => {
     describe('normalize', () => {
     describe('normalize', () => {
         let optionsPreset: TInputOptions,
         let optionsPreset: TInputOptions,
@@ -41,13 +48,13 @@ describe('OptionsNormalizer', () => {
         describe('controlFlowFlatteningThresholdRule', () => {
         describe('controlFlowFlatteningThresholdRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     controlFlowFlattening: true,
                     controlFlowFlattening: true,
                     controlFlowFlatteningThreshold: 0
                     controlFlowFlatteningThreshold: 0
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     controlFlowFlattening: false,
                     controlFlowFlattening: false,
                     controlFlowFlatteningThreshold: 0
                     controlFlowFlatteningThreshold: 0
                 };
                 };
@@ -61,7 +68,7 @@ describe('OptionsNormalizer', () => {
         describe('deadCodeInjectionRule', () => {
         describe('deadCodeInjectionRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     deadCodeInjection: true,
                     deadCodeInjection: true,
                     deadCodeInjectionThreshold: 0.4,
                     deadCodeInjectionThreshold: 0.4,
                     stringArray: false,
                     stringArray: false,
@@ -69,7 +76,7 @@ describe('OptionsNormalizer', () => {
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     deadCodeInjection: true,
                     deadCodeInjection: true,
                     deadCodeInjectionThreshold: 0.4,
                     deadCodeInjectionThreshold: 0.4,
                     stringArray: true,
                     stringArray: true,
@@ -86,7 +93,7 @@ describe('OptionsNormalizer', () => {
             describe('`stringArrayThreshold` option is empty', () => {
             describe('`stringArrayThreshold` option is empty', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         deadCodeInjection: true,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 0.4,
                         deadCodeInjectionThreshold: 0.4,
                         stringArray: false,
                         stringArray: false,
@@ -94,7 +101,7 @@ describe('OptionsNormalizer', () => {
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         deadCodeInjection: true,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 0.4,
                         deadCodeInjectionThreshold: 0.4,
                         stringArray: true,
                         stringArray: true,
@@ -110,7 +117,7 @@ describe('OptionsNormalizer', () => {
             describe('`stringArrayThreshold` option is not empty', () => {
             describe('`stringArrayThreshold` option is not empty', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         deadCodeInjection: true,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 0.4,
                         deadCodeInjectionThreshold: 0.4,
                         stringArray: false,
                         stringArray: false,
@@ -118,7 +125,7 @@ describe('OptionsNormalizer', () => {
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         deadCodeInjection: true,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 0.4,
                         deadCodeInjectionThreshold: 0.4,
                         stringArray: true,
                         stringArray: true,
@@ -135,13 +142,13 @@ describe('OptionsNormalizer', () => {
         describe('deadCodeInjectionThresholdRule', () => {
         describe('deadCodeInjectionThresholdRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     deadCodeInjection: true,
                     deadCodeInjection: true,
                     deadCodeInjectionThreshold: 0
                     deadCodeInjectionThreshold: 0
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     deadCodeInjection: false,
                     deadCodeInjection: false,
                     deadCodeInjectionThreshold: 0
                     deadCodeInjectionThreshold: 0
                 };
                 };
@@ -155,7 +162,7 @@ describe('OptionsNormalizer', () => {
         describe('domainLockRule', () => {
         describe('domainLockRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     domainLock: [
                     domainLock: [
                         '//localhost:9000',
                         '//localhost:9000',
                         'https://google.ru/abc?cde=fgh'
                         'https://google.ru/abc?cde=fgh'
@@ -163,7 +170,7 @@ describe('OptionsNormalizer', () => {
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     domainLock: [
                     domainLock: [
                         'localhost',
                         'localhost',
                         'google.ru'
                         'google.ru'
@@ -180,12 +187,12 @@ describe('OptionsNormalizer', () => {
             describe('Variant #1: extension isn\'t set', () => {
             describe('Variant #1: extension isn\'t set', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: 'foo'
                         inputFileName: 'foo'
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: 'foo.js'
                         inputFileName: 'foo.js'
                     };
                     };
                 });
                 });
@@ -198,12 +205,12 @@ describe('OptionsNormalizer', () => {
             describe('Variant #2: extension is set', () => {
             describe('Variant #2: extension is set', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: 'foo.js'
                         inputFileName: 'foo.js'
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: 'foo.js'
                         inputFileName: 'foo.js'
                     };
                     };
                 });
                 });
@@ -216,12 +223,12 @@ describe('OptionsNormalizer', () => {
             describe('Variant #3: extension in set with `.map` postfix', () => {
             describe('Variant #3: extension in set with `.map` postfix', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: 'foo.map.js'
                         inputFileName: 'foo.map.js'
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: 'foo.map.js'
                         inputFileName: 'foo.map.js'
                     };
                     };
                 });
                 });
@@ -234,12 +241,12 @@ describe('OptionsNormalizer', () => {
             describe('Variant #4: no file name', () => {
             describe('Variant #4: no file name', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: ''
                         inputFileName: ''
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         inputFileName: ''
                         inputFileName: ''
                     };
                     };
                 });
                 });
@@ -250,16 +257,72 @@ describe('OptionsNormalizer', () => {
             });
             });
         });
         });
 
 
+        describe('seedRule', () => {
+            describe('Variant #1: seed value is string', () => {
+                before(() => {
+                    optionsPreset = getNormalizedOptions({
+                        ...getDefaultOptions(),
+                        seed: 'abc'
+                    });
+
+                    expectedOptionsPreset = {
+                        ...getDefaultOptions(),
+                        seed: 'abc'
+                    };
+                });
+
+                it('should not normalize options preset', () => {
+                    assert.deepEqual(optionsPreset, expectedOptionsPreset);
+                });
+            });
+
+            describe('Variant #2: seed value is number', () => {
+                before(() => {
+                    optionsPreset = getNormalizedOptions({
+                        ...getDefaultOptions(),
+                        seed: 123
+                    });
+
+                    expectedOptionsPreset = {
+                        ...getDefaultOptions(),
+                        seed: 123
+                    };
+                });
+
+                it('should normalize options preset', () => {
+                    assert.deepEqual(optionsPreset, expectedOptionsPreset);
+                });
+            });
+
+            describe('Variant #3: seed value is `0``', () => {
+                let seedValue: number;
+
+                before(() => {
+                    optionsPreset = getNormalizedOptions({
+                        ...getDefaultOptions(),
+                        seed: 0
+                    });
+
+                    seedValue = Number(optionsPreset.seed);
+                });
+
+                it('should normalize seed value', () => {
+                    assert.isAtLeast(seedValue, 0);
+                    assert.isBelow(seedValue, 999_999_999);
+                });
+            });
+        });
+
         describe('selfDefendingRule', () => {
         describe('selfDefendingRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     selfDefending: true,
                     selfDefending: true,
                     compact: false
                     compact: false
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     selfDefending: true,
                     selfDefending: true,
                     compact: true
                     compact: true
                 };
                 };
@@ -274,12 +337,12 @@ describe('OptionsNormalizer', () => {
             describe('Variant #1: only source map base url', () => {
             describe('Variant #1: only source map base url', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         sourceMapBaseUrl: 'http://localhost:9000',
                         sourceMapBaseUrl: 'http://localhost:9000',
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         sourceMapBaseUrl: ''
                         sourceMapBaseUrl: ''
                     };
                     };
                 });
                 });
@@ -292,13 +355,13 @@ describe('OptionsNormalizer', () => {
             describe('Variant #2: source map base url with source map file name', () => {
             describe('Variant #2: source map base url with source map file name', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         sourceMapBaseUrl: 'http://localhost:9000',
                         sourceMapBaseUrl: 'http://localhost:9000',
                         sourceMapFileName: '/outputSourceMapName.map'
                         sourceMapFileName: '/outputSourceMapName.map'
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         sourceMapBaseUrl: 'http://localhost:9000/',
                         sourceMapBaseUrl: 'http://localhost:9000/',
                         sourceMapFileName: 'outputSourceMapName.js.map'
                         sourceMapFileName: 'outputSourceMapName.js.map'
                     };
                     };
@@ -313,13 +376,13 @@ describe('OptionsNormalizer', () => {
         describe('sourceMapFileNameRule', () => {
         describe('sourceMapFileNameRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     sourceMapBaseUrl: 'http://localhost:9000',
                     sourceMapBaseUrl: 'http://localhost:9000',
                     sourceMapFileName: '//outputSourceMapName'
                     sourceMapFileName: '//outputSourceMapName'
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     sourceMapBaseUrl: 'http://localhost:9000/',
                     sourceMapBaseUrl: 'http://localhost:9000/',
                     sourceMapFileName: 'outputSourceMapName.js.map'
                     sourceMapFileName: 'outputSourceMapName.js.map'
                 };
                 };
@@ -334,13 +397,13 @@ describe('OptionsNormalizer', () => {
             describe('`splitStringsChunkLengthRule` value is float number', () => {
             describe('`splitStringsChunkLengthRule` value is float number', () => {
                 before(() => {
                 before(() => {
                     optionsPreset = getNormalizedOptions({
                     optionsPreset = getNormalizedOptions({
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         splitStrings: true,
                         splitStrings: true,
                         splitStringsChunkLength: 5.6
                         splitStringsChunkLength: 5.6
                     });
                     });
 
 
                     expectedOptionsPreset = {
                     expectedOptionsPreset = {
-                        ...DEFAULT_PRESET,
+                        ...getDefaultOptions(),
                         splitStrings: true,
                         splitStrings: true,
                         splitStringsChunkLength: 5
                         splitStringsChunkLength: 5
                     };
                     };
@@ -355,7 +418,7 @@ describe('OptionsNormalizer', () => {
         describe('stringArrayRule', () => {
         describe('stringArrayRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     stringArray: false,
                     stringArray: false,
                     stringArrayEncoding: StringArrayEncoding.Rc4,
                     stringArrayEncoding: StringArrayEncoding.Rc4,
                     stringArrayThreshold: 0.5,
                     stringArrayThreshold: 0.5,
@@ -363,7 +426,7 @@ describe('OptionsNormalizer', () => {
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     stringArray: false,
                     stringArray: false,
                     stringArrayEncoding: false,
                     stringArrayEncoding: false,
                     stringArrayThreshold: 0,
                     stringArrayThreshold: 0,
@@ -379,12 +442,12 @@ describe('OptionsNormalizer', () => {
         describe('stringArrayEncodingRule', () => {
         describe('stringArrayEncodingRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     stringArrayEncoding: true
                     stringArrayEncoding: true
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     stringArrayEncoding: StringArrayEncoding.Base64
                     stringArrayEncoding: StringArrayEncoding.Base64
                 };
                 };
             });
             });
@@ -397,14 +460,14 @@ describe('OptionsNormalizer', () => {
         describe('stringArrayThresholdRule', () => {
         describe('stringArrayThresholdRule', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     rotateStringArray: true,
                     rotateStringArray: true,
                     stringArray: true,
                     stringArray: true,
                     stringArrayThreshold: 0
                     stringArrayThreshold: 0
                 });
                 });
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
-                    ...DEFAULT_PRESET,
+                    ...getDefaultOptions(),
                     rotateStringArray: false,
                     rotateStringArray: false,
                     stringArray: false,
                     stringArray: false,
                     stringArrayThreshold: 0
                     stringArrayThreshold: 0

+ 45 - 7
test/functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec.ts

@@ -5,6 +5,7 @@ import { readFileAsString } from '../../../helpers/readFileAsString';
 
 
 import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 
+import { IdentifierNamesGenerator } from '../../../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
 import { ObfuscationTarget } from '../../../../src/enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../../../src/enums/ObfuscationTarget';
 
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscatorFacade';
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscatorFacade';
@@ -29,7 +30,7 @@ function spawnThread(inputCallback: Function, threadCallback: Function, timeoutC
 }
 }
 
 
 describe('DebugProtectionFunctionCallTemplate', () => {
 describe('DebugProtectionFunctionCallTemplate', () => {
-    describe('Variant #1: correctly obfuscated code`', () => {
+    describe('Variant #1: correctly obfuscate code with `HexadecimalIdentifierNamesGenerator``', () => {
         const expectedEvaluationResult: number = 1;
         const expectedEvaluationResult: number = 1;
 
 
         let obfuscatedCode: string,
         let obfuscatedCode: string,
@@ -42,7 +43,43 @@ describe('DebugProtectionFunctionCallTemplate', () => {
                 code,
                 code,
                 {
                 {
                     ...NO_ADDITIONAL_NODES_PRESET,
                     ...NO_ADDITIONAL_NODES_PRESET,
-                    debugProtection: true
+                    debugProtection: true,
+                    identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
+                }
+            ).getObfuscatedCode();
+
+            spawnThread(
+                () => obfuscatedCode,
+                (response: number) => {
+                    evaluationResult = response;
+                    done();
+                },
+                () => {
+                    done();
+                }
+            );
+        });
+
+        it('should correctly evaluate code with enabled debug protection', () => {
+            assert.equal(evaluationResult, expectedEvaluationResult);
+        });
+    });
+
+    describe('Variant #2: correctly obfuscate code with `MangledIdentifierNamesGenerator` option', () => {
+        const expectedEvaluationResult: number = 1;
+
+        let obfuscatedCode: string,
+            evaluationResult: number = 0;
+
+        beforeEach((done) => {
+            const code: string = readFileAsString(__dirname + '/fixtures/input.js');
+
+            obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                code,
+                {
+                    ...NO_ADDITIONAL_NODES_PRESET,
+                    debugProtection: true,
+                    identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator
                 }
                 }
             ).getObfuscatedCode();
             ).getObfuscatedCode();
 
 
@@ -63,7 +100,7 @@ describe('DebugProtectionFunctionCallTemplate', () => {
         });
         });
     });
     });
 
 
-    describe('Variant #2: correctly obfuscated code with enabled `mangle` option', () => {
+    describe('Variant #3: correctly obfuscate code with `DictionaryIdentifierNamesGenerator` option', () => {
         const expectedEvaluationResult: number = 1;
         const expectedEvaluationResult: number = 1;
 
 
         let obfuscatedCode: string,
         let obfuscatedCode: string,
@@ -77,7 +114,8 @@ describe('DebugProtectionFunctionCallTemplate', () => {
                 {
                 {
                     ...NO_ADDITIONAL_NODES_PRESET,
                     ...NO_ADDITIONAL_NODES_PRESET,
                     debugProtection: true,
                     debugProtection: true,
-                    mangle: true
+                    identifierNamesGenerator: IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
+                    identifiersDictionary: ['foo', 'bar', 'baz', 'bark', 'hawk', 'eagle']
                 }
                 }
             ).getObfuscatedCode();
             ).getObfuscatedCode();
 
 
@@ -98,7 +136,7 @@ describe('DebugProtectionFunctionCallTemplate', () => {
         });
         });
     });
     });
 
 
-    describe('Variant #3: correctly obfuscated code with target `extension`', () => {
+    describe('Variant #4: correctly obfuscated code with target `BrowserNoEval`', () => {
         const expectedEvaluationResult: number = 1;
         const expectedEvaluationResult: number = 1;
 
 
         let obfuscatedCode: string,
         let obfuscatedCode: string,
@@ -133,7 +171,7 @@ describe('DebugProtectionFunctionCallTemplate', () => {
         });
         });
     });
     });
 
 
-    describe('Variant #4: obfuscated code with removed debug protection code', () => {
+    describe('Variant #5: obfuscated code with removed debug protection code', () => {
         const expectedEvaluationResult: number = 0;
         const expectedEvaluationResult: number = 0;
 
 
         let obfuscatedCode: string,
         let obfuscatedCode: string,
@@ -168,7 +206,7 @@ describe('DebugProtectionFunctionCallTemplate', () => {
         });
         });
     });
     });
 
 
-    describe('Variant #5: single call of debug protection code', () => {
+    describe('Variant #6: single call of debug protection code', () => {
         const expectedEvaluationResult: number = 1;
         const expectedEvaluationResult: number = 1;
 
 
         let obfuscatedCode: string,
         let obfuscatedCode: string,

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov