Pārlūkot izejas kodu

`shuffleStringArray` option

sanex3339 5 gadi atpakaļ
vecāks
revīzija
1edf96c0a0
28 mainītis faili ar 388 papildinājumiem un 84 dzēšanām
  1. 2 0
      CHANGELOG.md
  2. 12 0
      README.md
  3. 0 0
      dist/index.browser.js
  4. 0 0
      dist/index.cli.js
  5. 0 0
      dist/index.js
  6. 5 6
      src/analyzers/string-array-storage-analyzer/StringArrayStorageAnalyzer.ts
  7. 5 1
      src/cli/JavaScriptObfuscatorCLI.ts
  8. 2 2
      src/container/modules/storages/StoragesModule.ts
  9. 6 25
      src/custom-nodes/string-array-nodes/StringArrayNode.ts
  10. 5 5
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  11. 11 19
      src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts
  12. 1 0
      src/interfaces/options/IOptions.d.ts
  13. 24 0
      src/interfaces/storages/string-array-storage/IStringArrayStorage.d.ts
  14. 29 9
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.ts
  15. 6 0
      src/options/Options.ts
  16. 1 0
      src/options/normalizer-rules/StringArrayRule.ts
  17. 1 0
      src/options/presets/Default.ts
  18. 1 0
      src/options/presets/NoCustomNodes.ts
  19. 82 9
      src/storages/string-array/StringArrayStorage.ts
  20. 1 1
      src/templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate.ts
  21. 0 5
      src/types/storages/TStringArrayStorage.d.ts
  22. 5 1
      test/dev/dev.ts
  23. 2 1
      test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts
  24. 4 0
      test/functional-tests/options/OptionsNormalizer.spec.ts
  25. 3 0
      test/index.spec.ts
  26. 60 0
      test/unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/BooleanLiteralObfuscatingReplacer.spec.ts
  27. 60 0
      test/unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/NumberLiteralObfuscatingReplacer.spec.ts
  28. 60 0
      test/unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.spec.ts

+ 2 - 0
CHANGELOG.md

@@ -2,7 +2,9 @@ Change Log
 
 
 v0.23.0
 v0.23.0
 ---
 ---
+* **New option:** `shuffleStringArray` randomly shuffles string array items
 * **Internal change:** switched AST parser from `espree` on `acorn`
 * **Internal change:** switched AST parser from `espree` on `acorn`
+* **Internal refactoring:** refactoring of string array storage and related things
 
 
 v0.22.1
 v0.22.1
 ---
 ---

+ 12 - 0
README.md

@@ -306,6 +306,7 @@ Following options are available for the JS Obfuscator:
     rotateStringArray: true,
     rotateStringArray: true,
     seed: 0,
     seed: 0,
     selfDefending: false,
     selfDefending: false,
+    shuffleStringArray: true,
     sourceMap: false,
     sourceMap: false,
     sourceMapBaseUrl: '',
     sourceMapBaseUrl: '',
     sourceMapFileName: '',
     sourceMapFileName: '',
@@ -349,6 +350,7 @@ Following options are available for the JS Obfuscator:
     --rotate-string-array <boolean>
     --rotate-string-array <boolean>
     --seed <string|number>
     --seed <string|number>
     --self-defending <boolean>
     --self-defending <boolean>
+    --shuffle-string-array <boolean>
     --source-map <boolean>
     --source-map <boolean>
     --source-map-base-url <string>
     --source-map-base-url <string>
     --source-map-file-name <string>
     --source-map-file-name <string>
@@ -691,6 +693,13 @@ Type: `boolean` Default: `false`
 
 
 This option makes the output code resilient against formatting and variable renaming. If one tries to use a JavaScript beautifier on the obfuscated code, the code won't work anymore, making it harder to understand and modify it.
 This option makes the output code resilient against formatting and variable renaming. If one tries to use a JavaScript beautifier on the obfuscated code, the code won't work anymore, making it harder to understand and modify it.
 
 
+### `shuffleStringArray`
+Type: `boolean` Default: `true`
+
+##### :warning: [`stringArray`](#stringarray) must be enabled
+
+Randomly shuffles the `stringArray` array items.
+
 ### `sourceMap`
 ### `sourceMap`
 Type: `boolean` Default: `false`
 Type: `boolean` Default: `false`
 
 
@@ -867,6 +876,7 @@ Performance will 50-100% slower than without obfuscation
     renameGlobals: false,
     renameGlobals: false,
     rotateStringArray: true,
     rotateStringArray: true,
     selfDefending: true,
     selfDefending: true,
+    shuffleStringArray: true,
     splitStrings: true,
     splitStrings: true,
     splitStringsChunkLength: '5',
     splitStringsChunkLength: '5',
     stringArray: true,
     stringArray: true,
@@ -896,6 +906,7 @@ Performance will 30-35% slower than without obfuscation
     renameGlobals: false,
     renameGlobals: false,
     rotateStringArray: true,
     rotateStringArray: true,
     selfDefending: true,
     selfDefending: true,
+    shuffleStringArray: true,
     splitStrings: true,
     splitStrings: true,
     splitStringsChunkLength: '10',
     splitStringsChunkLength: '10',
     stringArray: true,
     stringArray: true,
@@ -923,6 +934,7 @@ Performance will slightly slower than without obfuscation
     renameGlobals: false,
     renameGlobals: false,
     rotateStringArray: true,
     rotateStringArray: true,
     selfDefending: true,
     selfDefending: true,
+    shuffleStringArray: true,
     splitStrings: false,
     splitStrings: false,
     stringArray: true,
     stringArray: true,
     stringArrayEncoding: false,
     stringArrayEncoding: false,

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/index.browser.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/index.cli.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/index.js


+ 5 - 6
src/analyzers/string-array-storage-analyzer/StringArrayStorageAnalyzer.ts

@@ -4,10 +4,9 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as estraverse from 'estraverse';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
-import { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
-
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
 import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
 import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
 import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
 import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
 
 
@@ -35,9 +34,9 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
     private readonly randomGenerator: IRandomGenerator;
     private readonly randomGenerator: IRandomGenerator;
 
 
     /**
     /**
-     * @type {TStringArrayStorage}
+     * @type {IStringArrayStorage}
      */
      */
-    private readonly stringArrayStorage: TStringArrayStorage;
+    private readonly stringArrayStorage: IStringArrayStorage;
 
 
     /**
     /**
      * @type {Map<ESTree.Literal, IStringArrayStorageItemData>}
      * @type {Map<ESTree.Literal, IStringArrayStorageItemData>}
@@ -45,12 +44,12 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
     private readonly stringArrayStorageData: Map<ESTree.Literal, IStringArrayStorageItemData> = new Map();
     private readonly stringArrayStorageData: Map<ESTree.Literal, IStringArrayStorageItemData> = new Map();
 
 
     /**
     /**
-     * @param {TStringArrayStorage} stringArrayStorage
+     * @param {IStringArrayStorage} stringArrayStorage
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
-        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
+        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
     ) {
     ) {

+ 5 - 1
src/cli/JavaScriptObfuscatorCLI.ts

@@ -283,7 +283,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
                 BooleanSanitizer
                 BooleanSanitizer
             )
             )
             .option(
             .option(
-                '--rotate-string-array <boolean>', 'Disable rotation of unicode array values during obfuscation',
+                '--rotate-string-array <boolean>', 'Enable rotation of string array values during obfuscation',
                 BooleanSanitizer
                 BooleanSanitizer
             )
             )
             .option(
             .option(
@@ -296,6 +296,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
                 'Disables self-defending for obfuscated code',
                 'Disables self-defending for obfuscated code',
                 BooleanSanitizer
                 BooleanSanitizer
             )
             )
+            .option(
+                '--shuffle-string-array <boolean>', 'Randomly shuffles string array items',
+                BooleanSanitizer
+            )
             .option(
             .option(
                 '--source-map <boolean>',
                 '--source-map <boolean>',
                 'Enables source map generation',
                 'Enables source map generation',

+ 2 - 2
src/container/modules/storages/StoragesModule.ts

@@ -3,10 +3,10 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TCustomNodeGroupStorage } from '../../../types/storages/TCustomNodeGroupStorage';
 import { TCustomNodeGroupStorage } from '../../../types/storages/TCustomNodeGroupStorage';
-import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
 
 
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
 
 
 import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
 import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
 import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
 import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
@@ -18,7 +18,7 @@ export const storagesModule: interfaces.ContainerModule = new ContainerModule((b
         .to(CustomNodeGroupStorage)
         .to(CustomNodeGroupStorage)
         .inSingletonScope();
         .inSingletonScope();
 
 
-    bind<TStringArrayStorage>(ServiceIdentifiers.TStringArrayStorage)
+    bind<IStringArrayStorage>(ServiceIdentifiers.TStringArrayStorage)
         .to(StringArrayStorage)
         .to(StringArrayStorage)
         .inSingletonScope();
         .inSingletonScope();
 
 

+ 6 - 25
src/custom-nodes/string-array-nodes/StringArrayNode.ts

@@ -3,11 +3,11 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 import { TStatement } from '../../types/node/TStatement';
-import { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
+import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -15,15 +15,14 @@ import { StringArrayTemplate } from '../../templates/string-array-nodes/string-a
 
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeUtils } from '../../node/NodeUtils';
 import { NodeUtils } from '../../node/NodeUtils';
-import { StringArrayStorage } from '../../storages/string-array/StringArrayStorage';
 
 
 @injectable()
 @injectable()
 export class StringArrayNode extends AbstractCustomNode {
 export class StringArrayNode extends AbstractCustomNode {
     /**
     /**
-     * @type {TStringArrayStorage}
+     * @type {IStringArrayStorage}
      */
      */
     @initializable()
     @initializable()
-    private stringArrayStorage!: TStringArrayStorage;
+    private stringArrayStorage!: IStringArrayStorage;
 
 
     /**
     /**
      * @type {string}
      * @type {string}
@@ -31,12 +30,6 @@ export class StringArrayNode extends AbstractCustomNode {
     @initializable()
     @initializable()
     private stringArrayName!: string;
     private stringArrayName!: string;
 
 
-    /**
-     * @type {number}
-     */
-    @initializable()
-    private stringArrayRotateValue!: number;
-
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {ICustomNodeFormatter} customNodeFormatter
@@ -54,27 +47,15 @@ export class StringArrayNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
-     * @param {TStringArrayStorage} stringArrayStorage
+     * @param {IStringArrayStorage} stringArrayStorage
      * @param {string} stringArrayName
      * @param {string} stringArrayName
-     * @param {number} stringArrayRotateValue
      */
      */
     public initialize (
     public initialize (
-        stringArrayStorage: TStringArrayStorage,
-        stringArrayName: string,
-        stringArrayRotateValue: number
+        stringArrayStorage: IStringArrayStorage,
+        stringArrayName: string
     ): void {
     ): void {
         this.stringArrayStorage = stringArrayStorage;
         this.stringArrayStorage = stringArrayStorage;
         this.stringArrayName = stringArrayName;
         this.stringArrayName = stringArrayName;
-        this.stringArrayRotateValue = stringArrayRotateValue;
-    }
-
-    /**
-     * @returns {TStatement[]}
-     */
-    public getNode (): TStatement[] {
-        (<StringArrayStorage>this.stringArrayStorage).rotateStorage(this.stringArrayRotateValue);
-
-        return super.getNode();
     }
     }
 
 
     /**
     /**

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

@@ -38,7 +38,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
      * @param {number}
      * @param {number}
      */
      */
     @initializable()
     @initializable()
-    private stringArrayRotateValue!: number;
+    private stringArrayRotationAmount!: number;
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
@@ -62,14 +62,14 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {string} stringArrayName
      * @param {string} stringArrayName
-     * @param {number} stringArrayRotateValue
+     * @param {number} stringArrayRotationAmount
      */
      */
     public initialize (
     public initialize (
         stringArrayName: string,
         stringArrayName: string,
-        stringArrayRotateValue: number
+        stringArrayRotationAmount: number
     ): void {
     ): void {
         this.stringArrayName = stringArrayName;
         this.stringArrayName = stringArrayName;
-        this.stringArrayRotateValue = stringArrayRotateValue;
+        this.stringArrayRotationAmount = stringArrayRotationAmount;
     }
     }
 
 
     /**
     /**
@@ -103,7 +103,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
                 code,
                 code,
                 timesName,
                 timesName,
                 stringArrayName: this.stringArrayName,
                 stringArrayName: this.stringArrayName,
-                stringArrayRotateValue: NumberUtils.toHex(this.stringArrayRotateValue),
+                stringArrayRotationAmount: NumberUtils.toHex(this.stringArrayRotationAmount),
                 whileFunctionName
                 whileFunctionName
             }),
             }),
             {
             {

+ 11 - 19
src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts

@@ -5,12 +5,12 @@ import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCusto
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TInitialData } from '../../../types/TInitialData';
 import { TInitialData } from '../../../types/TInitialData';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
-import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
 
 
+import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
 
 
 import { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -42,20 +42,20 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
     private readonly customNodeFactory: TCustomNodeFactory;
     private readonly customNodeFactory: TCustomNodeFactory;
 
 
     /**
     /**
-     * @type {TStringArrayStorage}
+     * @type {IStringArrayStorage}
      */
      */
-    private readonly stringArrayStorage: TStringArrayStorage;
+    private readonly stringArrayStorage: IStringArrayStorage;
 
 
     /**
     /**
      * @param {TCustomNodeFactory} customNodeFactory
      * @param {TCustomNodeFactory} customNodeFactory
-     * @param {TStringArrayStorage} stringArrayStorage
+     * @param {IStringArrayStorage} stringArrayStorage
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
+        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@@ -106,21 +106,13 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
         const stringArrayRotateFunctionNode: ICustomNode<TInitialData<StringArrayRotateFunctionNode>> =
         const stringArrayRotateFunctionNode: ICustomNode<TInitialData<StringArrayRotateFunctionNode>> =
             this.customNodeFactory(CustomNode.StringArrayRotateFunctionNode);
             this.customNodeFactory(CustomNode.StringArrayRotateFunctionNode);
 
 
-        const stringArrayStorageId: string = this.stringArrayStorage.getStorageId();
-
-        const [stringArrayName, stringArrayCallsWrapperName]: string[] = stringArrayStorageId.split('|');
-
-        let stringArrayRotateValue: number;
-
-        if (this.options.rotateStringArray) {
-            stringArrayRotateValue = this.randomGenerator.getRandomInteger(100, 500);
-        } else {
-            stringArrayRotateValue = 0;
-        }
+        const stringArrayName: string = this.stringArrayStorage.getStorageName();
+        const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName();
+        const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
 
 
-        stringArrayNode.initialize(this.stringArrayStorage, stringArrayName, stringArrayRotateValue);
+        stringArrayNode.initialize(this.stringArrayStorage, stringArrayName);
         stringArrayCallsWrapper.initialize(stringArrayName, stringArrayCallsWrapperName);
         stringArrayCallsWrapper.initialize(stringArrayName, stringArrayCallsWrapperName);
-        stringArrayRotateFunctionNode.initialize(stringArrayName, stringArrayRotateValue);
+        stringArrayRotateFunctionNode.initialize(stringArrayName, stringArrayRotationAmount);
 
 
         this.customNodes.set(CustomNode.StringArrayNode, stringArrayNode);
         this.customNodes.set(CustomNode.StringArrayNode, stringArrayNode);
         this.customNodes.set(CustomNode.StringArrayCallsWrapper, stringArrayCallsWrapper);
         this.customNodes.set(CustomNode.StringArrayCallsWrapper, stringArrayCallsWrapper);

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

@@ -27,6 +27,7 @@ export interface IOptions {
     readonly rotateStringArray: boolean;
     readonly rotateStringArray: boolean;
     readonly seed: string | number;
     readonly seed: string | number;
     readonly selfDefending: boolean;
     readonly selfDefending: boolean;
+    readonly shuffleStringArray: boolean;
     readonly sourceMap: boolean;
     readonly sourceMap: boolean;
     readonly sourceMapBaseUrl: string;
     readonly sourceMapBaseUrl: string;
     readonly sourceMapFileName: string;
     readonly sourceMapFileName: string;

+ 24 - 0
src/interfaces/storages/string-array-storage/IStringArrayStorage.d.ts

@@ -0,0 +1,24 @@
+import { IStringArrayStorageItemData } from './IStringArrayStorageItem';
+
+import { IMapStorage } from '../IMapStorage';
+
+export interface IStringArrayStorage extends IMapStorage <string, IStringArrayStorageItemData> {
+    /**
+     * @returns {number}
+     */
+    getRotationAmount (): number;
+
+    /**
+     * @returns {string}
+     */
+    getStorageName (): string;
+
+    /**
+     * @returns {string}
+     */
+    getStorageCallsWrapperName (): string;
+
+    rotateStorage (): void;
+
+    shuffleStorage (): void;
+}

+ 29 - 9
src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.ts

@@ -1,15 +1,17 @@
-import { inject, injectable, } from 'inversify';
+import { inject, injectable, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
 
 
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
-import { TStringArrayStorage } from '../../../../types/storages/TStringArrayStorage';
-
 import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
+import { IInitializable } from '../../../../interfaces/IInitializable';
 import { IOptions } from '../../../../interfaces/options/IOptions';
 import { IOptions } from '../../../../interfaces/options/IOptions';
+import { IStringArrayStorage } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorage';
 import { IStringArrayStorageAnalyzer } from '../../../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
 import { IStringArrayStorageAnalyzer } from '../../../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
 import { IStringArrayStorageItemData } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
 import { IStringArrayStorageItemData } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
 
 
+import { initializable } from '../../../../decorators/Initializable';
+
 import { StringArrayEncoding } from '../../../../enums/StringArrayEncoding';
 import { StringArrayEncoding } from '../../../../enums/StringArrayEncoding';
 
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
@@ -19,7 +21,7 @@ import { NumberUtils } from '../../../../utils/NumberUtils';
 import { Utils } from '../../../../utils/Utils';
 import { Utils } from '../../../../utils/Utils';
 
 
 @injectable()
 @injectable()
-export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer {
+export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer implements IInitializable {
     /**
     /**
      * @type {IEscapeSequenceEncoder}
      * @type {IEscapeSequenceEncoder}
      */
      */
@@ -30,6 +32,11 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      */
      */
     private readonly nodesCache: Map <string, ESTree.Node> = new Map();
     private readonly nodesCache: Map <string, ESTree.Node> = new Map();
 
 
+    /**
+     * @type {IStringArrayStorage}
+     */
+    private readonly stringArrayStorage: IStringArrayStorage;
+
     /**
     /**
      * @type {IStringArrayStorageAnalyzer}
      * @type {IStringArrayStorageAnalyzer}
      */
      */
@@ -38,26 +45,26 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
     /**
     /**
      * @type {string}
      * @type {string}
      */
      */
-    private readonly stringArrayStorageCallsWrapperName: string;
+    @initializable()
+    private stringArrayStorageCallsWrapperName!: string;
 
 
     /**
     /**
-     * @param {TStringArrayStorage} stringArrayStorage
+     * @param {IStringArrayStorage} stringArrayStorage
      * @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
      * @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
-        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
+        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
         @inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
         @inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
         super(options);
         super(options);
 
 
+        this.stringArrayStorage = stringArrayStorage;
         this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
         this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
-
-        this.stringArrayStorageCallsWrapperName = stringArrayStorage.getStorageId().split('|')[1];
     }
     }
 
 
     /**
     /**
@@ -84,6 +91,19 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
         return rc4KeyLiteralNode;
         return rc4KeyLiteralNode;
     }
     }
 
 
+    @postConstruct()
+    public initialize (): void {
+        this.stringArrayStorageCallsWrapperName = this.stringArrayStorage.getStorageCallsWrapperName();
+
+        if (this.options.shuffleStringArray) {
+            this.stringArrayStorage.shuffleStorage();
+        }
+
+        if (this.options.rotateStringArray) {
+            this.stringArrayStorage.rotateStorage();
+        }
+    }
+
     /**
     /**
      * @param {SimpleLiteral} literalNode
      * @param {SimpleLiteral} literalNode
      * @returns {Node}
      * @returns {Node}

+ 6 - 0
src/options/Options.ts

@@ -188,6 +188,12 @@ export class Options implements IOptions {
     @IsBoolean()
     @IsBoolean()
     public readonly selfDefending!: boolean;
     public readonly selfDefending!: boolean;
 
 
+    /**
+     * @type {boolean}
+     */
+    @IsBoolean()
+    public readonly shuffleStringArray!: boolean;
+
     /**
     /**
      * @type {boolean}
      * @type {boolean}
      */
      */

+ 1 - 0
src/options/normalizer-rules/StringArrayRule.ts

@@ -11,6 +11,7 @@ export const StringArrayRule: TOptionsNormalizerRule = (options: IOptions): IOpt
         options = {
         options = {
             ...options,
             ...options,
             rotateStringArray: false,
             rotateStringArray: false,
+            shuffleStringArray: false,
             stringArray: false,
             stringArray: false,
             stringArrayEncoding: false,
             stringArrayEncoding: false,
             stringArrayThreshold: 0
             stringArrayThreshold: 0

+ 1 - 0
src/options/presets/Default.ts

@@ -27,6 +27,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
     rotateStringArray: true,
     rotateStringArray: true,
     seed: 0,
     seed: 0,
     selfDefending: false,
     selfDefending: false,
+    shuffleStringArray: true,
     sourceMap: false,
     sourceMap: false,
     sourceMapBaseUrl: '',
     sourceMapBaseUrl: '',
     sourceMapFileName: '',
     sourceMapFileName: '',

+ 1 - 0
src/options/presets/NoCustomNodes.ts

@@ -26,6 +26,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
     rotateStringArray: false,
     rotateStringArray: false,
     seed: 0,
     seed: 0,
     selfDefending: false,
     selfDefending: false,
+    shuffleStringArray: false,
     sourceMap: false,
     sourceMap: false,
     sourceMapBaseUrl: '',
     sourceMapBaseUrl: '',
     sourceMapFileName: '',
     sourceMapFileName: '',

+ 82 - 9
src/storages/string-array/StringArrayStorage.ts

@@ -10,14 +10,17 @@ import { IEncodedValue } from '../../interfaces/IEncodedValue';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
 import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
 import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
 
 
+import { initializable } from '../../decorators/Initializable';
+
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
 
 
 import { MapStorage } from '../MapStorage';
 import { MapStorage } from '../MapStorage';
 
 
 @injectable()
 @injectable()
-export class StringArrayStorage extends MapStorage <string, IStringArrayStorageItemData> {
+export class StringArrayStorage extends MapStorage <string, IStringArrayStorageItemData> implements IStringArrayStorage {
     /**
     /**
      * @type {number}
      * @type {number}
      */
      */
@@ -58,6 +61,23 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
      */
      */
     private readonly rc4Keys: string[];
     private readonly rc4Keys: string[];
 
 
+    /**
+     * @type {number}
+     */
+    private rotationAmount: number = 0;
+
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private stringArrayStorageName!: string;
+
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private stringArrayStorageCallsWrapperName!: string;
+
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {IArrayUtils} arrayUtils
      * @param {IArrayUtils} arrayUtils
@@ -99,10 +119,13 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
             .generate(StringArrayStorage.stringArrayNameLength);
             .generate(StringArrayStorage.stringArrayNameLength);
         const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator
         const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator
             .generate(StringArrayStorage.stringArrayNameLength);
             .generate(StringArrayStorage.stringArrayNameLength);
-        const stringArrayName: string = `${this.options.identifiersPrefix}${baseStringArrayName}`;
-        const stringArrayCallsWrapperName: string = `${this.options.identifiersPrefix}${baseStringArrayCallsWrapperName}`;
 
 
-        this.storageId = `${stringArrayName}|${stringArrayCallsWrapperName}`;
+        this.stringArrayStorageName = `${this.options.identifiersPrefix}${baseStringArrayName}`;
+        this.stringArrayStorageCallsWrapperName = `${this.options.identifiersPrefix}${baseStringArrayCallsWrapperName}`;
+
+        this.rotationAmount = this.options.rotateStringArray
+            ? this.randomGenerator.getRandomInteger(100, 500)
+            : 0;
     }
     }
 
 
     /**
     /**
@@ -114,26 +137,76 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
     }
     }
 
 
     /**
     /**
-     * @param {number} rotationAmount
+     * @returns {number}
      */
      */
-    public rotateStorage (rotationAmount: number): void {
+    public getRotationAmount (): number {
+        return this.rotationAmount;
+    }
+
+    /**
+     * @returns {string}
+     */
+    public getStorageId (): string {
+        return this.stringArrayStorageName;
+    }
+
+    /**
+     * @returns {string}
+     */
+    public getStorageName (): string {
+        return this.getStorageId();
+    }
+
+    /**
+     * @returns {string}
+     */
+    public getStorageCallsWrapperName (): string {
+        return this.stringArrayStorageCallsWrapperName;
+    }
+
+    public rotateStorage (): void {
+        if (!this.getLength()) {
+            return;
+        }
+
         this.storage = new Map(
         this.storage = new Map(
             this.arrayUtils.rotate(
             this.arrayUtils.rotate(
                 Array.from(this.storage.entries()),
                 Array.from(this.storage.entries()),
-                rotationAmount
+                this.rotationAmount
             )
             )
         );
         );
     }
     }
 
 
+    public shuffleStorage (): void {
+        this.storage = new Map(
+            this.arrayUtils
+                .shuffle(Array.from(this.storage.entries()))
+                .map<[string, IStringArrayStorageItemData]>(
+                    (
+                        [value, stringArrayStorageItemData]: [string, IStringArrayStorageItemData],
+                        index: number
+                    ) => {
+                        stringArrayStorageItemData.index = index;
+
+                        return [value, stringArrayStorageItemData];
+                    }
+                )
+                .sort((
+                    [, stringArrayStorageItemDataA]: [string, IStringArrayStorageItemData],
+                    [, stringArrayStorageItemDataB]: [string, IStringArrayStorageItemData]
+                ) => stringArrayStorageItemDataA.index - stringArrayStorageItemDataB.index)
+        );
+    }
+
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
     public toString (): string {
     public toString (): string {
         return Array
         return Array
             .from(this.storage.values())
             .from(this.storage.values())
-            .map((item: IStringArrayStorageItemData) => {
+            .map((stringArrayStorageItemData: IStringArrayStorageItemData) => {
                 return `'${this.escapeSequenceEncoder.encode(
                 return `'${this.escapeSequenceEncoder.encode(
-                    item.encodedValue,
+                    stringArrayStorageItemData.encodedValue,
                     this.options.unicodeEscapeSequence
                     this.options.unicodeEscapeSequence
                 )}'`;
                 )}'`;
             }).toString();
             }).toString();

+ 1 - 1
src/templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate.ts

@@ -11,6 +11,6 @@ export function StringArrayRotateFunctionTemplate (): string {
             };
             };
             
             
             {code}
             {code}
-        })({stringArrayName}, 0x{stringArrayRotateValue});
+        })({stringArrayName}, 0x{stringArrayRotationAmount});
     `;
     `;
 }
 }

+ 0 - 5
src/types/storages/TStringArrayStorage.d.ts

@@ -1,5 +0,0 @@
-import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
-
-import { IMapStorage } from '../../interfaces/storages/IMapStorage';
-
-export type TStringArrayStorage = IMapStorage <string, IStringArrayStorageItemData>;

+ 5 - 1
test/dev/dev.ts

@@ -11,11 +11,15 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
             var bar = 'bar';
             var bar = 'bar';
             var baz = 'baz';
             var baz = 'baz';
             var bark = 'bark';
             var bark = 'bark';
+            
+            console.log(foo, bar, baz, bark);
         `,
         `,
         {
         {
             ...NO_ADDITIONAL_NODES_PRESET,
             ...NO_ADDITIONAL_NODES_PRESET,
             stringArray: true,
             stringArray: true,
-            stringArrayThreshold: 1
+            stringArrayThreshold: 1,
+            rotateStringArray: true,
+            shuffleStringArray: true
         }
         }
     ).getObfuscatedCode();
     ).getObfuscatedCode();
 
 

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

@@ -1,6 +1,8 @@
 import { assert } from 'chai';
 import { assert } from 'chai';
 import { TypeFromEnum } from '@gradecam/tsenum';
 import { TypeFromEnum } from '@gradecam/tsenum';
 
 
+import { TInputOptions } from '../../../src/types/options/TInputOptions';
+
 import { IObfuscatedCode } from '../../../src/interfaces/source-code/IObfuscatedCode';
 import { IObfuscatedCode } from '../../../src/interfaces/source-code/IObfuscatedCode';
 
 
 import { SourceMapMode } from '../../../src/enums/source-map/SourceMapMode';
 import { SourceMapMode } from '../../../src/enums/source-map/SourceMapMode';
@@ -15,7 +17,6 @@ import { IdentifierNamesGenerator } from '../../../src/enums/generators/identifi
 import { buildLargeCode } from '../../helpers/buildLargeCode';
 import { buildLargeCode } from '../../helpers/buildLargeCode';
 import { getRegExpMatch } from '../../helpers/getRegExpMatch';
 import { getRegExpMatch } from '../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../helpers/readFileAsString';
 import { readFileAsString } from '../../helpers/readFileAsString';
-import { TInputOptions } from '../../../src/types/options/TInputOptions';
 
 
 describe('JavaScriptObfuscator', () => {
 describe('JavaScriptObfuscator', () => {
     describe('obfuscate', () => {
     describe('obfuscate', () => {

+ 4 - 0
test/functional-tests/options/OptionsNormalizer.spec.ts

@@ -541,6 +541,7 @@ describe('OptionsNormalizer', () => {
             before(() => {
             before(() => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
                     ...getDefaultOptions(),
                     ...getDefaultOptions(),
+                    shuffleStringArray: true,
                     stringArray: false,
                     stringArray: false,
                     stringArrayEncoding: StringArrayEncoding.Rc4,
                     stringArrayEncoding: StringArrayEncoding.Rc4,
                     stringArrayThreshold: 0.5,
                     stringArrayThreshold: 0.5,
@@ -549,6 +550,7 @@ describe('OptionsNormalizer', () => {
 
 
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
                     ...getDefaultOptions(),
                     ...getDefaultOptions(),
+                    shuffleStringArray: false,
                     stringArray: false,
                     stringArray: false,
                     stringArrayEncoding: false,
                     stringArrayEncoding: false,
                     stringArrayThreshold: 0,
                     stringArrayThreshold: 0,
@@ -584,6 +586,7 @@ describe('OptionsNormalizer', () => {
                 optionsPreset = getNormalizedOptions({
                 optionsPreset = getNormalizedOptions({
                     ...getDefaultOptions(),
                     ...getDefaultOptions(),
                     rotateStringArray: true,
                     rotateStringArray: true,
+                    shuffleStringArray: true,
                     stringArray: true,
                     stringArray: true,
                     stringArrayThreshold: 0
                     stringArrayThreshold: 0
                 });
                 });
@@ -591,6 +594,7 @@ describe('OptionsNormalizer', () => {
                 expectedOptionsPreset = {
                 expectedOptionsPreset = {
                     ...getDefaultOptions(),
                     ...getDefaultOptions(),
                     rotateStringArray: false,
                     rotateStringArray: false,
+                    shuffleStringArray: false,
                     stringArray: false,
                     stringArray: false,
                     stringArrayThreshold: 0
                     stringArrayThreshold: 0
                 };
                 };

+ 3 - 0
test/index.spec.ts

@@ -29,6 +29,9 @@ import './unit-tests/node/node-lexical-scope-utils/NodeLexicalScopeUtils.spec';
 import './unit-tests/node/node-statement-utils/NodeStatementUtils.spec';
 import './unit-tests/node/node-statement-utils/NodeStatementUtils.spec';
 import './unit-tests/node/node-utils/NodeUtils.spec';
 import './unit-tests/node/node-utils/NodeUtils.spec';
 import './unit-tests/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.spec';
 import './unit-tests/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.spec';
+import './unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/BooleanLiteralObfuscatingReplacer.spec';
+import './unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/NumberLiteralObfuscatingReplacer.spec';
+import './unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.spec';
 import './unit-tests/options/ValidationErrorsFormatter.spec';
 import './unit-tests/options/ValidationErrorsFormatter.spec';
 import './unit-tests/source-code/ObfuscatedCode.spec';
 import './unit-tests/source-code/ObfuscatedCode.spec';
 import './unit-tests/storages/ArrayStorage.spec';
 import './unit-tests/storages/ArrayStorage.spec';

+ 60 - 0
test/unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/BooleanLiteralObfuscatingReplacer.spec.ts

@@ -0,0 +1,60 @@
+import 'reflect-metadata';
+
+import { assert } from 'chai';
+import * as ESTree from 'estree';
+
+import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
+import { IObfuscatingReplacer } from '../../../../../../src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
+
+import { LiteralObfuscatingReplacer } from '../../../../../../src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
+import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
+
+import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
+import { NodeFactory } from '../../../../../../src/node/NodeFactory';
+
+describe('BooleanLiteralObfuscatingReplacer', () => {
+    describe('replace', () => {
+        let inversifyContainerFacade: IInversifyContainerFacade,
+            obfuscatingReplacer: IObfuscatingReplacer;
+
+        before(() => {
+            inversifyContainerFacade = new InversifyContainerFacade();
+            inversifyContainerFacade.load('', '', {});
+
+            obfuscatingReplacer = inversifyContainerFacade
+                .getNamed(ServiceIdentifiers.IObfuscatingReplacer, LiteralObfuscatingReplacer.BooleanLiteralObfuscatingReplacer);
+        });
+
+        describe('Variant #1: literal value type check', () => {
+            describe('Variant #1: literal values is a `boolean` value', () => {
+                let testFunc: () => void;
+
+                before(() => {
+                    const literalNode: ESTree.Literal = NodeFactory.literalNode(true);
+
+                    testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
+                });
+
+                it('should not throw an error if literal values is a `boolean` value', () => {
+                    assert.doesNotThrow(testFunc,);
+                });
+            });
+
+            describe('Variant #2: literal values is not a `boolean` value', () => {
+                const expectedError: ErrorConstructor = Error;
+
+                let testFunc: () => void;
+
+                before(() => {
+                    const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
+
+                    testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
+                });
+
+                it('should throw an error if literal values is not a `boolean` value', () => {
+                    assert.throws(testFunc, expectedError);
+                });
+            });
+        });
+    });
+});

+ 60 - 0
test/unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/NumberLiteralObfuscatingReplacer.spec.ts

@@ -0,0 +1,60 @@
+import 'reflect-metadata';
+
+import { assert } from 'chai';
+import * as ESTree from 'estree';
+
+import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
+import { IObfuscatingReplacer } from '../../../../../../src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
+
+import { LiteralObfuscatingReplacer } from '../../../../../../src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
+import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
+
+import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
+import { NodeFactory } from '../../../../../../src/node/NodeFactory';
+
+describe('NumberLiteralObfuscatingReplacer', () => {
+    describe('replace', () => {
+        let inversifyContainerFacade: IInversifyContainerFacade,
+            obfuscatingReplacer: IObfuscatingReplacer;
+
+        before(() => {
+            inversifyContainerFacade = new InversifyContainerFacade();
+            inversifyContainerFacade.load('', '', {});
+
+            obfuscatingReplacer = inversifyContainerFacade
+                .getNamed(ServiceIdentifiers.IObfuscatingReplacer, LiteralObfuscatingReplacer.NumberLiteralObfuscatingReplacer);
+        });
+
+        describe('Variant #1: literal value type check', () => {
+            describe('Variant #1: literal values is a `number` value', () => {
+                let testFunc: () => void;
+
+                before(() => {
+                    const literalNode: ESTree.Literal = NodeFactory.literalNode(1);
+
+                    testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
+                });
+
+                it('should not throw an error if literal values is a `number` value', () => {
+                    assert.doesNotThrow(testFunc,);
+                });
+            });
+
+            describe('Variant #2: literal values is not a `number` value', () => {
+                const expectedError: ErrorConstructor = Error;
+
+                let testFunc: () => void;
+
+                before(() => {
+                    const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
+
+                    testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
+                });
+
+                it('should throw an error if literal values is not a `number` value', () => {
+                    assert.throws(testFunc, expectedError);
+                });
+            });
+        });
+    });
+});

+ 60 - 0
test/unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.spec.ts

@@ -0,0 +1,60 @@
+import 'reflect-metadata';
+
+import { assert } from 'chai';
+import * as ESTree from 'estree';
+
+import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
+import { IObfuscatingReplacer } from '../../../../../../src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
+
+import { LiteralObfuscatingReplacer } from '../../../../../../src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
+import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
+
+import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
+import { NodeFactory } from '../../../../../../src/node/NodeFactory';
+
+describe('StringLiteralObfuscatingReplacer', () => {
+    describe('replace', () => {
+        let inversifyContainerFacade: IInversifyContainerFacade,
+            obfuscatingReplacer: IObfuscatingReplacer;
+
+        before(() => {
+            inversifyContainerFacade = new InversifyContainerFacade();
+            inversifyContainerFacade.load('', '', {});
+
+            obfuscatingReplacer = inversifyContainerFacade
+                .getNamed(ServiceIdentifiers.IObfuscatingReplacer, LiteralObfuscatingReplacer.StringLiteralObfuscatingReplacer);
+        });
+
+        describe('Variant #1: literal value type check', () => {
+            describe('Variant #1: literal values is a `string` value', () => {
+                let testFunc: () => void;
+
+                before(() => {
+                    const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
+
+                    testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
+                });
+
+                it('should not throw an error if literal values is a `string` value', () => {
+                    assert.doesNotThrow(testFunc,);
+                });
+            });
+
+            describe('Variant #2: literal values is not a `string` value', () => {
+                const expectedError: ErrorConstructor = Error;
+
+                let testFunc: () => void;
+
+                before(() => {
+                    const literalNode: ESTree.Literal = NodeFactory.literalNode(1);
+
+                    testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
+                });
+
+                it('should throw an error if literal values is not a `string` value', () => {
+                    assert.throws(testFunc, expectedError);
+                });
+            });
+        });
+    });
+});

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels