ソースを参照

Eval obfuscation transformers

sanex3339 7 年 前
コミット
ad0b1b0fdf
100 ファイル変更1593 行追加2546 行削除
  1. 2 0
      CHANGELOG.md
  2. 42 0
      README.md
  3. 0 1891
      dist/index.js
  4. 11 10
      package.json
  5. 31 14
      src/JavaScriptObfuscator.ts
  6. 1 18
      src/ObfuscationResult.ts
  7. 5 0
      src/cli/JavaScriptObfuscatorCLI.ts
  8. 5 7
      src/container/InversifyContainerFacade.ts
  9. 1 0
      src/container/ServiceIdentifiers.ts
  10. 18 1
      src/container/modules/custom-nodes/CustomNodesModule.ts
  11. 13 3
      src/container/modules/node-transformers/ConvertingTransformersModule.ts
  12. 3 3
      src/custom-nodes/AbstractCustomNodeGroup.ts
  13. 4 4
      src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts
  14. 89 0
      src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts
  15. 4 4
      src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts
  16. 4 4
      src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts
  17. 2 2
      src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts
  18. 2 2
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  19. 4 4
      src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts
  20. 2 2
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  21. 2 2
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  22. 3 3
      src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts
  23. 1 0
      src/declarations/ESTree.d.ts
  24. 5 0
      src/declarations/js-string-escape.d.ts
  25. 3 3
      src/enums/analyzers/stack-trace-analyzer/CalleeDataExtractor.ts
  26. 9 9
      src/enums/custom-nodes/ControlFlowCustomNode.ts
  27. 10 10
      src/enums/custom-nodes/CustomNode.ts
  28. 5 5
      src/enums/custom-nodes/CustomNodeGroup.ts
  29. 3 0
      src/enums/custom-nodes/DeadCodeInjectionCustomNode.ts
  30. 2 0
      src/enums/logger/LoggingMessage.ts
  31. 20 18
      src/enums/node-transformers/NodeTransformer.ts
  32. 4 4
      src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/ControlFlowReplacer.ts
  33. 1 1
      src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer.ts
  34. 3 3
      src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer.ts
  35. 2 2
      src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.ts
  36. 2 0
      src/enums/node/NodeType.ts
  37. 0 7
      src/interfaces/IObfuscationResult.d.ts
  38. 2 2
      src/interfaces/custom-nodes/ICustomNodeGroup.d.ts
  39. 1 0
      src/interfaces/options/IOptions.d.ts
  40. 1 4
      src/interfaces/source-map/ISourceMapCorrector.d.ts
  41. 7 1
      src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts
  42. 9 9
      src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts
  43. 56 0
      src/node-transformers/converting-transformers/AstToEvalCallExpressionTransformer.ts
  44. 0 84
      src/node-transformers/converting-transformers/CallExpressionTransformer.ts
  45. 72 0
      src/node-transformers/converting-transformers/EvaCallExpressionToAstTransformer.ts
  46. 230 0
      src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts
  47. 36 32
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
  48. 6 6
      src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts
  49. 6 6
      src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts
  50. 2 2
      src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts
  51. 101 74
      src/node/NodeAppender.ts
  52. 53 4
      src/node/NodeGuards.ts
  53. 89 110
      src/node/NodeUtils.ts
  54. 24 0
      src/node/Nodes.ts
  55. 6 0
      src/options/Options.ts
  56. 1 0
      src/options/presets/Default.ts
  57. 2 1
      src/options/presets/NoCustomNodes.ts
  58. 1 5
      src/source-map/SourceMapCorrector.ts
  59. 1 3
      src/types/container/TObfuscationResultFactory.d.ts
  60. 5 0
      src/types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory.d.ts
  61. 3 0
      src/types/node/TNodeWithBlockScope.d.ts
  62. 0 3
      src/types/node/TNodeWithBlockStatement.d.ts
  63. 3 0
      src/types/node/TNodeWithScope.d.ts
  64. 6 3
      test/dev/dev.ts
  65. 11 11
      test/functional-tests/analyzers/stack-trace-analyzer/StackTraceAnalyzer.spec.ts
  66. 3 3
      test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts
  67. 3 3
      test/functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec.ts
  68. 3 3
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayCallsWrapper.spec.ts
  69. 3 3
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayNode.spec.ts
  70. 3 3
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.spec.ts
  71. 10 9
      test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts
  72. 16 15
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts
  73. 3 3
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec.ts
  74. 4 4
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec.ts
  75. 5 5
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec.ts
  76. 2 2
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/StringLiteralControlFlowReplacer.spec.ts
  77. 9 9
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts
  78. 5 5
      test/functional-tests/node-transformers/converting-transformers/member-expression-transformer/MemberExpressionTransformer.spec.ts
  79. 4 4
      test/functional-tests/node-transformers/converting-transformers/method-definition-transformer/MethodDefinitionTransformer.spec.ts
  80. 319 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec.ts
  81. 3 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/integration-with-control-flow-flattening.js
  82. 10 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/nested-objects-1.js
  83. 14 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/nested-objects-2.js
  84. 8 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-catch-clause.js
  85. 7 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-if-statement.js
  86. 8 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-switch-case.js
  87. 7 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-try-statement.js
  88. 6 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/simple.js
  89. 7 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declaration-without-initialization.js
  90. 5 5
      test/functional-tests/node-transformers/converting-transformers/template-literal-transformer/TemplateLiteralTransformer.spec.ts
  91. 10 10
      test/functional-tests/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.spec.ts
  92. 3 3
      test/functional-tests/node-transformers/obfuscating-transformers/catch-clause-transformer/CatchClauseTransformer.spec.ts
  93. 4 4
      test/functional-tests/node-transformers/obfuscating-transformers/class-declaration-transformer/ClassDeclarationTransformer.spec.ts
  94. 6 6
      test/functional-tests/node-transformers/obfuscating-transformers/function-declaration-transformer/FunctionDeclarationTransformer.spec.ts
  95. 8 8
      test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/FunctionTransformer.spec.ts
  96. 2 2
      test/functional-tests/node-transformers/obfuscating-transformers/labeled-statement-transformer/LabeledStatementTransformer.spec.ts
  97. 15 15
      test/functional-tests/node-transformers/obfuscating-transformers/literal-transformer/LiteralTransformer.spec.ts
  98. 4 4
      test/functional-tests/node-transformers/obfuscating-transformers/object-expression-transformer/ObjectExpressionTransformer.spec.ts
  99. 15 15
      test/functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts
  100. 7 7
      test/functional-tests/node-transformers/preparing-transformers/comments-transformer/CommentsTransformer.spec.ts

+ 2 - 0
CHANGELOG.md

@@ -2,7 +2,9 @@ Change Log
 ===
 v0.14.0
 ---
+* **New option:** `transformObjectKeys` enables object keys transformation and obfuscation.
 * **Breaking change:** Now CLI obfuscating directory recursively. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/157
+* Obfuscator now can obfuscate `eval` expressions.
 * Fixed runtime errors when `deadCodeInjection` is enabled and `identifierNamesGenerator` is set to `mangled`
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/166
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/156

+ 42 - 0
README.md

@@ -291,6 +291,7 @@ Following options are available for the JS Obfuscator:
     stringArrayEncoding: false,
     stringArrayThreshold: 0.75,
     target: 'browser',
+    transformObjectKeys: false,
     unicodeEscapeSequence: false
 }
 ```
@@ -327,6 +328,7 @@ Following options are available for the JS Obfuscator:
     --string-array-encoding <boolean|string> [true, false, base64, rc4]
     --string-array-threshold <number>
     --target <string> [browser, extension, node]
+    --transform-object-keys <boolean>
     --unicode-escape-sequence <boolean>
 ```
 
@@ -707,6 +709,44 @@ Available values:
 Currently output code for `browser` and `node` targets is identical.
 Output code for `extension` target is not using `eval`.
 
+### `transformObjectKeys`
+Type: `boolean` Default: `false`
+
+Enables transformation of object keys.
+
+Example:
+```ts
+// input
+(function(){
+    var object = {
+        foo: 'test1',
+        bar: {
+            baz: 'test2'
+        }
+    };
+})();
+
+// output
+var _0x5a21 = [
+    'foo',
+    'test1',
+    'bar',
+    'baz',
+    'test2'
+];
+var _0x223f = function (_0x474dc0, _0x10db96) {
+    _0x474dc0 = _0x474dc0 - 0x0;
+    var _0x4c8bf7 = _0x5a21[_0x474dc0];
+    return _0x4c8bf7;
+};
+(function () {
+    var _0x2e1a8e = {};
+    _0x2e1a8e[_0x223f('0x0')] = _0x223f('0x1');
+    _0x2e1a8e[_0x223f('0x2')] = {};
+    _0x2e1a8e[_0x223f('0x2')][_0x223f('0x3')] = _0x223f('0x4');
+}());
+```
+
 ### `unicodeEscapeSequence`
 Type: `boolean` Default: `false`
 
@@ -737,6 +777,7 @@ Performance will 50-100% slower than without obfuscation
     stringArray: true,
     stringArrayEncoding: 'rc4',
     stringArrayThreshold: 1,
+    transformObjectKeys: true,
     unicodeEscapeSequence: false
 }
 ```
@@ -763,6 +804,7 @@ Performance will 30-35% slower than without obfuscation
     stringArray: true,
     stringArrayEncoding: 'base64',
     stringArrayThreshold: 0.75,
+    transformObjectKeys: true,
     unicodeEscapeSequence: false
 }
 ```

ファイルの差分が大きいため隠しています
+ 0 - 1891
dist/index.js


+ 11 - 10
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.14.0-beta.1",
+  "version": "0.14.0-beta.2",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -23,22 +23,23 @@
     "chance": "1.0.13",
     "class-validator": "0.7.3",
     "commander": "2.12.2",
-    "escodegen-wallaby": "1.6.15",
+    "escodegen-wallaby": "1.6.16",
     "esprima": "4.0.0",
     "estraverse": "4.2.0",
     "inversify": "4.9.0",
+    "js-string-escape": "1.0.1",
     "md5": "2.2.1",
     "mkdirp": "0.5.1",
     "opencollective": "1.0.3",
-    "pjson": "^1.0.9",
+    "pjson": "1.0.9",
     "reflect-metadata": "0.1.10",
     "source-map-support": "0.5.0",
     "string-template": "1.0.0",
     "tslib": "1.8.1"
   },
   "devDependencies": {
-    "@types/chai": "4.0.10",
-    "@types/chance": "0.7.35",
+    "@types/chai": "4.1.0",
+    "@types/chance": "0.7.36",
     "@types/commander": "2.12.2",
     "@types/escodegen": "0.0.6",
     "@types/esprima": "4.0.1",
@@ -46,9 +47,9 @@
     "@types/estree": "0.0.38",
     "@types/md5": "2.1.32",
     "@types/mkdirp": "0.5.2",
-    "@types/mocha": "2.2.45",
-    "@types/node": "8.5.2",
-    "@types/rimraf": "^2.0.2",
+    "@types/mocha": "2.2.46",
+    "@types/node": "8.5.7",
+    "@types/rimraf": "2.0.2",
     "@types/sinon": "4.1.2",
     "@types/string-template": "1.0.2",
     "@types/webpack-env": "1.13.3",
@@ -62,9 +63,9 @@
     "istanbul": "1.1.0-alpha.1",
     "mocha": "4.1.0",
     "pre-commit": "1.2.2",
-    "rimraf": "^2.6.2",
+    "rimraf": "2.6.2",
     "sinon": "4.1.3",
-    "threads": "^0.10.0",
+    "threads": "0.10.0",
     "ts-node": "4.1.0",
     "tslint": "5.8.0",
     "tslint-eslint-rules": "4.1.1",

+ 31 - 14
src/JavaScriptObfuscator.ts

@@ -48,10 +48,18 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
     /**
      * @type {NodeTransformer[]}
      */
-    private static readonly convertingTransformersList: NodeTransformer[] = [
-        NodeTransformer.CallExpressionTransformer,
+    private static readonly postObfuscationConvertingTransformersList: NodeTransformer[] = [
+        NodeTransformer.AstToEvalCallExpressionTransformer
+    ];
+
+    /**
+     * @type {NodeTransformer[]}
+     */
+    private static readonly preObfuscationConvertingTransformersList: NodeTransformer[] = [
+        NodeTransformer.EvalCallExpressionToAstTransformer,
         NodeTransformer.MemberExpressionTransformer,
         NodeTransformer.MethodDefinitionTransformer,
+        NodeTransformer.ObjectExpressionKeysTransformer,
         NodeTransformer.TemplateLiteralTransformer
     ];
 
@@ -177,7 +185,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
         const obfuscationTime: number = (Date.now() - timeStart) / 1000;
         this.logger.success(LoggingMessage.ObfuscationCompleted, obfuscationTime);
 
-        return this.getObfuscationResult(obfuscatedAstTree, generatorOutput);
+        return this.getObfuscationResult(generatorOutput);
     }
 
     /**
@@ -251,12 +259,26 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
             );
         }
 
-        // fifth pass: converting and obfuscating transformers
+        // fifth pass: pre-obfuscation converting transformers
+        this.logger.info(LoggingMessage.StagePreObfuscation);
+        astTree = this.transformersRunner.transform(
+            astTree,
+            JavaScriptObfuscator.preObfuscationConvertingTransformersList
+        );
+
+        // sixth pass: obfuscating transformers
         this.logger.info(LoggingMessage.StageObfuscation);
-        astTree = this.transformersRunner.transform(astTree, [
-            ...JavaScriptObfuscator.convertingTransformersList,
-            ...JavaScriptObfuscator.obfuscatingTransformersList
-        ]);
+        astTree = this.transformersRunner.transform(
+            astTree,
+            JavaScriptObfuscator.obfuscatingTransformersList
+        );
+
+        // seventh pass: post-obfuscation converting transformers
+        this.logger.info(LoggingMessage.StagePostObfuscation);
+        astTree = this.transformersRunner.transform(
+            astTree,
+            JavaScriptObfuscator.postObfuscationConvertingTransformersList
+        );
 
         this.obfuscationEventEmitter.emit(ObfuscationEvent.AfterObfuscation, astTree, stackTraceData);
 
@@ -291,16 +313,11 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
     }
 
     /**
-     * @param {Program} obfuscatedAstTree
      * @param {IGeneratorOutput} generatorOutput
      * @returns {IObfuscationResult}
      */
-    private getObfuscationResult (
-        obfuscatedAstTree: ESTree.Program,
-        generatorOutput: IGeneratorOutput
-    ): IObfuscationResult {
+    private getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult {
         return this.sourceMapCorrector.correct(
-            obfuscatedAstTree,
             generatorOutput.code,
             generatorOutput.map
         );

+ 1 - 18
src/ObfuscationResult.ts

@@ -1,19 +1,11 @@
 import { injectable } from 'inversify';
 
-import { Program } from 'estree';
-
 import { IObfuscationResult } from './interfaces/IObfuscationResult';
 
 import { initializable } from './decorators/Initializable';
 
 @injectable()
 export class ObfuscationResult implements IObfuscationResult {
-    /**
-     * @type {Program}
-     */
-    @initializable()
-    private obfuscatedAst: Program;
-
     /**
      * @type {string}
      */
@@ -27,23 +19,14 @@ export class ObfuscationResult implements IObfuscationResult {
     private sourceMap: string;
 
     /**
-     * @param {Program} obfuscatedAst
      * @param {string} obfuscatedCode
      * @param {string} sourceMap
      */
-    public initialize (obfuscatedAst: Program, obfuscatedCode: string, sourceMap: string): void {
-        this.obfuscatedAst = obfuscatedAst;
+    public initialize (obfuscatedCode: string, sourceMap: string): void {
         this.obfuscatedCode = obfuscatedCode;
         this.sourceMap = sourceMap;
     }
 
-    /**
-     * @returns {Program}
-     */
-    public getObfuscatedAst (): Program {
-        return this.obfuscatedAst;
-    }
-
     /**
      * @returns {string}
      */

+ 5 - 0
src/cli/JavaScriptObfuscatorCLI.ts

@@ -309,6 +309,11 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
                 'Allows to set target environment for obfuscated code.',
                 ObfuscationTargetSanitizer
             )
+            .option(
+                '--transform-object-keys <boolean>',
+                'Enables transformation of object keys',
+                BooleanSanitizer
+            )
             .option(
                 '--unicode-escape-sequence <boolean>',
                 'Allows to enable/disable string conversion to unicode escape sequence',

+ 5 - 7
src/container/InversifyContainerFacade.ts

@@ -1,8 +1,6 @@
 import { Container, interfaces } from 'inversify';
 import { ServiceIdentifiers } from './ServiceIdentifiers';
 
-import * as ESTree from 'estree';
-
 import { analyzersModule } from './modules/analyzers/AnalyzersModule';
 import { controlFlowTransformersModule } from './modules/node-transformers/ControlFlowTransformersModule';
 import { convertingTransformersModule } from './modules/node-transformers/ConvertingTransformersModule';
@@ -49,7 +47,7 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
      * @param {interfaces.ServiceIdentifier<U>} serviceIdentifier
      * @returns {U}
      */
-    public static getFactory <T extends number, U> (
+    public static getFactory <T extends string, U> (
         serviceIdentifier: interfaces.ServiceIdentifier<U>
     ): (context: interfaces.Context) => (bindingName: T) => U {
         return (context: interfaces.Context): (bindingName: T) => U => {
@@ -63,7 +61,7 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
      * @param {interfaces.ServiceIdentifier<U>} serviceIdentifier
      * @returns {U}
      */
-    public static getCacheFactory <T extends number, U> (
+    public static getCacheFactory <T extends string, U> (
         serviceIdentifier: interfaces.ServiceIdentifier<U>
     ): (context: interfaces.Context) => (bindingName: T) => U {
         return (context: interfaces.Context): (bindingName: T) => U => {
@@ -88,7 +86,7 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
      * @param {any[]} dependencies
      * @returns {U}
      */
-    public static getConstructorFactory <T extends number, U> (
+    public static getConstructorFactory <T extends string, U> (
         serviceIdentifier: interfaces.ServiceIdentifier<interfaces.Newable<U>>,
         ...dependencies: any[]
     ): (context: interfaces.Context) => (bindingName: T) => U {
@@ -175,11 +173,11 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
         this.container
             .bind<IObfuscationResult>(ServiceIdentifiers.Factory__IObfuscationResult)
             .toFactory<IObfuscationResult>((context: interfaces.Context) => {
-                return (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string) => {
+                return (obfuscatedCode: string, sourceMap: string) => {
                     const obfuscationResult: IObfuscationResult = context.container
                         .get<IObfuscationResult>(ServiceIdentifiers.IObfuscationResult);
 
-                    obfuscationResult.initialize(obfuscatedAst, obfuscatedCode, sourceMap);
+                    obfuscationResult.initialize(obfuscatedCode, sourceMap);
 
                     return obfuscationResult;
                 };

+ 1 - 0
src/container/ServiceIdentifiers.ts

@@ -4,6 +4,7 @@ export enum ServiceIdentifiers {
     Factory__IControlFlowReplacer = 'Factory<IControlFlowReplacer>',
     Factory__ICustomNode = 'Factory<ICustomNode>',
     Factory__ICustomNodeGroup = 'Factory<ICustomNodeGroup>',
+    Factory__IDeadCodeInjectionCustomNode = 'Factory<IDeadCodeInjectionCustomNode>',
     Factory__IIdentifierNamesGenerator = 'Factory<IIdentifierNamesGenerator>',
     Factory__IIdentifierObfuscatingReplacer = 'Factory<IIdentifierObfuscatingReplacer>',
     Factory__INodeGuard = 'Factory<INodeGuard>',

+ 18 - 1
src/container/modules/custom-nodes/CustomNodesModule.ts

@@ -8,6 +8,7 @@ import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGr
 import { ControlFlowCustomNode } from "../../../enums/custom-nodes/ControlFlowCustomNode";
 import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
 import { CustomNodeGroup } from '../../../enums/custom-nodes/CustomNodeGroup';
+import { DeadCodeInjectionCustomNode } from '../../../enums/custom-nodes/DeadCodeInjectionCustomNode';
 
 import { ConsoleOutputCustomNodeGroup } from '../../../custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup';
 import { DebugProtectionCustomNodeGroup } from '../../../custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup';
@@ -17,6 +18,7 @@ import { StringArrayCustomNodeGroup } from '../../../custom-nodes/string-array-n
 
 import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode';
 import { BlockStatementControlFlowFlatteningNode } from '../../../custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode';
+import { BlockStatementDeadCodeInjectionNode } from '../../../custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode';
 import { CallExpressionControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode';
 import { CallExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode';
 import { ControlFlowStorageNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
@@ -114,6 +116,11 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .toConstructor(StringLiteralControlFlowStorageCallNode)
         .whenTargetNamed(ControlFlowCustomNode.StringLiteralControlFlowStorageCallNode);
 
+    // dead code injection custom nodes
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(BlockStatementDeadCodeInjectionNode)
+        .whenTargetNamed(DeadCodeInjectionCustomNode.BlockStatementDeadCodeInjectionNode);
+
     // node groups
     bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
         .to(ConsoleOutputCustomNodeGroup)
@@ -140,7 +147,7 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .toFactory<ICustomNode>(InversifyContainerFacade
             .getFactory<CustomNode, ICustomNode>(ServiceIdentifiers.ICustomNode));
 
-    // control flow storage customNode constructor factory
+    // control flow customNode constructor factory
     bind<ICustomNode>(ServiceIdentifiers.Factory__IControlFlowCustomNode)
         .toFactory<ICustomNode>(InversifyContainerFacade
             .getConstructorFactory<ControlFlowCustomNode, ICustomNode>(
@@ -150,6 +157,16 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
                 ServiceIdentifiers.IOptions
             ));
 
+    // dead code injection customNode constructor factory
+    bind<ICustomNode>(ServiceIdentifiers.Factory__IDeadCodeInjectionCustomNode)
+        .toFactory<ICustomNode>(InversifyContainerFacade
+            .getConstructorFactory<DeadCodeInjectionCustomNode, ICustomNode>(
+                ServiceIdentifiers.Newable__ICustomNode,
+                ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
+                ServiceIdentifiers.IRandomGenerator,
+                ServiceIdentifiers.IOptions
+            ));
+
     // customNodeGroup factory
     bind<ICustomNodeGroup>(ServiceIdentifiers.Factory__ICustomNodeGroup)
         .toFactory<ICustomNodeGroup>(InversifyContainerFacade

+ 13 - 3
src/container/modules/node-transformers/ConvertingTransformersModule.ts

@@ -5,16 +5,22 @@ import { INodeTransformer } from '../../../interfaces/node-transformers/INodeTra
 
 import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
 
-import { CallExpressionTransformer } from '../../../node-transformers/converting-transformers/CallExpressionTransformer';
+import { AstToEvalCallExpressionTransformer } from '../../../node-transformers/converting-transformers/AstToEvalCallExpressionTransformer';
+import { EvalCallExpressionToAstTransformer } from '../../../node-transformers/converting-transformers/EvaCallExpressionToAstTransformer';
 import { MemberExpressionTransformer } from '../../../node-transformers/converting-transformers/MemberExpressionTransformer';
 import { MethodDefinitionTransformer } from '../../../node-transformers/converting-transformers/MethodDefinitionTransformer';
+import { ObjectExpressionKeysTransformer } from '../../../node-transformers/converting-transformers/ObjectExpressionKeysTransformer';
 import { TemplateLiteralTransformer } from '../../../node-transformers/converting-transformers/TemplateLiteralTransformer';
 
 export const convertingTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // converting transformers
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
-        .to(CallExpressionTransformer)
-        .whenTargetNamed(NodeTransformer.CallExpressionTransformer);
+        .to(AstToEvalCallExpressionTransformer)
+        .whenTargetNamed(NodeTransformer.AstToEvalCallExpressionTransformer);
+
+    bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
+        .to(EvalCallExpressionToAstTransformer)
+        .whenTargetNamed(NodeTransformer.EvalCallExpressionToAstTransformer);
 
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
         .to(MemberExpressionTransformer)
@@ -24,6 +30,10 @@ export const convertingTransformersModule: interfaces.ContainerModule = new Cont
         .to(MethodDefinitionTransformer)
         .whenTargetNamed(NodeTransformer.MethodDefinitionTransformer);
 
+    bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
+        .to(ObjectExpressionKeysTransformer)
+        .whenTargetNamed(NodeTransformer.ObjectExpressionKeysTransformer);
+
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
         .to(TemplateLiteralTransformer)
         .whenTargetNamed(NodeTransformer.TemplateLiteralTransformer);

+ 3 - 3
src/custom-nodes/AbstractCustomNodeGroup.ts

@@ -2,7 +2,7 @@ import { inject, injectable } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
 import { TIdentifierNamesGeneratorFactory } from '../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TNodeWithBlockStatement } from '../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
 import { ICustomNodeGroup } from '../interfaces/custom-nodes/ICustomNodeGroup';
@@ -63,10 +63,10 @@ export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {IStackTraceData[]} stackTraceData
      */
-    public abstract appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void;
+    public abstract appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void;
 
     /**
      * @returns {ObfuscationEvent}

+ 4 - 4
src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts

@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
@@ -55,10 +55,10 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {IStackTraceData[]} stackTraceData
      */
-    public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
+    public appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void {
         const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // consoleOutputDisableExpressionNode append
@@ -73,7 +73,7 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
 
         // nodeCallsControllerFunctionNode append
         this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            let targetBlockScope: TNodeWithBlockStatement;
+            let targetBlockScope: TNodeWithBlockScope;
 
             if (stackTraceData.length) {
                 targetBlockScope = NodeAppender.getOptimalBlockScope(stackTraceData, randomStackTraceIndex, 1);

+ 89 - 0
src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts

@@ -0,0 +1,89 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import { BinaryOperator, BlockStatement } from 'estree';
+
+import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TStatement } from '../../types/node/TStatement';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+
+import { initializable } from '../../decorators/Initializable';
+
+import { AbstractCustomNode } from '../AbstractCustomNode';
+import { Nodes } from '../../node/Nodes';
+import { NodeUtils } from '../../node/NodeUtils';
+
+@injectable()
+export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
+    /**
+     * @type {BlockStatement}
+     */
+    @initializable()
+    private blockStatementNode: BlockStatement;
+
+    /**
+     * @type {BlockStatement}
+     */
+    @initializable()
+    private randomBlockStatementNode: BlockStatement;
+
+    /**
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(identifierNamesGeneratorFactory, randomGenerator, options);
+    }
+
+    /**
+     * @param {BlockStatement} blockStatementNode
+     * @param {BlockStatement} randomBlockStatementNode
+     */
+    public initialize (
+        blockStatementNode: BlockStatement,
+        randomBlockStatementNode: BlockStatement
+    ): void {
+        this.blockStatementNode = blockStatementNode;
+        this.randomBlockStatementNode = randomBlockStatementNode;
+    }
+
+    /**
+     * @returns {TStatement[]}
+     */
+    protected getNodeStructure (): TStatement[] {
+        const random1: boolean = this.randomGenerator.getMathRandom() > 0.5;
+        const random2: boolean = this.randomGenerator.getMathRandom() > 0.5;
+
+        const operator: BinaryOperator = random1 ? '===' : '!==';
+        const leftString: string = this.randomGenerator.getRandomString(5);
+        const rightString: string = random2 ? leftString : this.randomGenerator.getRandomString(5);
+
+        const [consequent, alternate]: [BlockStatement, BlockStatement] = random1 === random2
+            ? [this.blockStatementNode, this.randomBlockStatementNode]
+            : [this.randomBlockStatementNode, this.blockStatementNode];
+
+        const structure: BlockStatement = Nodes.getBlockStatementNode([
+            Nodes.getIfStatementNode(
+                Nodes.getBinaryExpressionNode(
+                    operator,
+                    Nodes.getLiteralNode(leftString),
+                    Nodes.getLiteralNode(rightString)
+                ),
+                consequent,
+                alternate
+            )
+        ]);
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
+    }
+}

+ 4 - 4
src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts

@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
@@ -55,10 +55,10 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {IStackTraceData[]} stackTraceData
      */
-    public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
+    public appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void {
         const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // debugProtectionFunctionCallNode append
@@ -86,7 +86,7 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
 
         // nodeCallsControllerFunctionNode append
         this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            let targetBlockScope: TNodeWithBlockStatement;
+            let targetBlockScope: TNodeWithBlockScope;
 
             if (stackTraceData.length) {
                 targetBlockScope = NodeAppender.getOptimalBlockScope(stackTraceData, randomStackTraceIndex, 1);

+ 4 - 4
src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts

@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
@@ -55,10 +55,10 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {IStackTraceData[]} stackTraceData
      */
-    public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
+    public appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void {
         const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // domainLockNode append
@@ -73,7 +73,7 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
 
         // nodeCallsControllerFunctionNode append
         this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            let targetBlockScope: TNodeWithBlockStatement;
+            let targetBlockScope: TNodeWithBlockScope;
 
             if (stackTraceData.length) {
                 targetBlockScope = NodeAppender.getOptimalBlockScope(stackTraceData, randomStackTraceIndex, 1);

+ 2 - 2
src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts

@@ -15,7 +15,7 @@ import { initializable } from '../../decorators/Initializable';
 
 import { SingleNodeCallControllerTemplate } from '../../templates/SingleNodeCallControllerTemplate';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
@@ -75,7 +75,7 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                 }),
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     identifierNamesGenerator: this.options.identifierNamesGenerator,
                     seed: this.options.seed
                 }

+ 2 - 2
src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
 
 import { SelfDefendingTemplate } from '../../templates/self-defending-nodes/self-defending-unicode-node/SelfDefendingTemplate';
 
@@ -75,7 +75,7 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
             {
-                ...NO_CUSTOM_NODES_PRESET,
+                ...NO_ADDITIONAL_NODES_PRESET,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 seed: this.options.seed,
                 unicodeEscapeSequence: true

+ 4 - 4
src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts

@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
@@ -55,10 +55,10 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {IStackTraceData[]} stackTraceData
      */
-    public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
+    public appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void {
         const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // selfDefendingUnicodeNode append
@@ -73,7 +73,7 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
 
         // nodeCallsControllerFunctionNode append
         this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            let targetBlockScope: TNodeWithBlockStatement;
+            let targetBlockScope: TNodeWithBlockScope;
 
             if (stackTraceData.length) {
                 targetBlockScope = NodeAppender.getOptimalBlockScope(stackTraceData, randomStackTraceIndex, 1);

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

@@ -15,7 +15,7 @@ import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
 
 import { AtobTemplate } from '../../templates/AtobTemplate';
 import { GlobalVariableNoEvalTemplate } from '../../templates/GlobalVariableNoEvalTemplate';
@@ -98,7 +98,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
                 stringArrayName: this.stringArrayName
             }),
             {
-                ...NO_CUSTOM_NODES_PRESET,
+                ...NO_ADDITIONAL_NODES_PRESET,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 seed: this.options.seed
             }

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

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
 
 import { SelfDefendingTemplate } from '../../templates/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate';
 import { StringArrayRotateFunctionTemplate } from '../../templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate';
@@ -105,7 +105,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
                 whileFunctionName
             }),
             {
-                ...NO_CUSTOM_NODES_PRESET,
+                ...NO_ADDITIONAL_NODES_PRESET,
                 identifierNamesGenerator: this.options.identifierNamesGenerator,
                 seed: this.options.seed
             }

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

@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
@@ -65,10 +65,10 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {IStackTraceData[]} stackTraceData
      */
-    public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
+    public appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void {
         if (!this.stringArrayStorage.getLength()) {
             return;
         }

+ 1 - 0
src/declarations/ESTree.d.ts

@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
 declare module 'estree' {
     interface BaseNode {
         ignoredNode?: boolean;
+        isEvalRoot?: boolean;
         obfuscatedNode?: boolean;
         parentNode?: ESTree.Node;
     }

+ 5 - 0
src/declarations/js-string-escape.d.ts

@@ -0,0 +1,5 @@
+declare module 'js-string-escape' {
+    function jsStringEscape (input: string): string;
+
+    export = jsStringEscape;
+}

+ 3 - 3
src/enums/analyzers/stack-trace-analyzer/CalleeDataExtractor.ts

@@ -1,5 +1,5 @@
 export enum CalleeDataExtractor {
-    FunctionDeclarationCalleeDataExtractor,
-    FunctionExpressionCalleeDataExtractor,
-    ObjectExpressionCalleeDataExtractor,
+    FunctionDeclarationCalleeDataExtractor = 'FunctionDeclarationCalleeDataExtractor',
+    FunctionExpressionCalleeDataExtractor = 'FunctionExpressionCalleeDataExtractor',
+    ObjectExpressionCalleeDataExtractor = 'ObjectExpressionCalleeDataExtractor',
 }

+ 9 - 9
src/enums/custom-nodes/ControlFlowCustomNode.ts

@@ -1,11 +1,11 @@
 export enum ControlFlowCustomNode {
-    BinaryExpressionFunctionNode,
-    BlockStatementControlFlowFlatteningNode,
-    CallExpressionControlFlowStorageCallNode,
-    CallExpressionFunctionNode,
-    ControlFlowStorageNode,
-    ExpressionWithOperatorControlFlowStorageCallNode,
-    LogicalExpressionFunctionNode,
-    StringLiteralControlFlowStorageCallNode,
-    StringLiteralNode,
+    BinaryExpressionFunctionNode = 'BinaryExpressionFunctionNode',
+    BlockStatementControlFlowFlatteningNode = 'BlockStatementControlFlowFlatteningNode',
+    CallExpressionControlFlowStorageCallNode = 'CallExpressionControlFlowStorageCallNode',
+    CallExpressionFunctionNode = 'CallExpressionFunctionNode',
+    ControlFlowStorageNode = 'ControlFlowStorageNode',
+    ExpressionWithOperatorControlFlowStorageCallNode = 'ExpressionWithOperatorControlFlowStorageCallNode',
+    LogicalExpressionFunctionNode = 'LogicalExpressionFunctionNode',
+    StringLiteralControlFlowStorageCallNode = 'StringLiteralControlFlowStorageCallNode',
+    StringLiteralNode = 'StringLiteralNode'
 }

+ 10 - 10
src/enums/custom-nodes/CustomNode.ts

@@ -1,12 +1,12 @@
 export enum CustomNode {
-    ConsoleOutputDisableExpressionNode,
-    DebugProtectionFunctionCallNode,
-    DebugProtectionFunctionIntervalNode,
-    DebugProtectionFunctionNode,
-    DomainLockNode,
-    NodeCallsControllerFunctionNode,
-    SelfDefendingUnicodeNode,
-    StringArrayCallsWrapper,
-    StringArrayNode,
-    StringArrayRotateFunctionNode
+    ConsoleOutputDisableExpressionNode = 'ConsoleOutputDisableExpressionNode',
+    DebugProtectionFunctionCallNode = 'DebugProtectionFunctionCallNode',
+    DebugProtectionFunctionIntervalNode = 'DebugProtectionFunctionIntervalNode',
+    DebugProtectionFunctionNode = 'DebugProtectionFunctionNode',
+    DomainLockNode = 'DomainLockNode',
+    NodeCallsControllerFunctionNode = 'NodeCallsControllerFunctionNode',
+    SelfDefendingUnicodeNode = 'SelfDefendingUnicodeNode',
+    StringArrayCallsWrapper = 'StringArrayCallsWrapper',
+    StringArrayNode = 'StringArrayNode',
+    StringArrayRotateFunctionNode = 'StringArrayRotateFunctionNode'
 }

+ 5 - 5
src/enums/custom-nodes/CustomNodeGroup.ts

@@ -1,7 +1,7 @@
 export enum CustomNodeGroup {
-    ConsoleOutputCustomNodeGroup,
-    DebugProtectionCustomNodeGroup,
-    DomainLockCustomNodeGroup,
-    SelfDefendingCustomNodeGroup,
-    StringArrayCustomNodeGroup
+    ConsoleOutputCustomNodeGroup = 'ConsoleOutputCustomNodeGroup',
+    DebugProtectionCustomNodeGroup = 'DebugProtectionCustomNodeGroup',
+    DomainLockCustomNodeGroup = 'DomainLockCustomNodeGroup',
+    SelfDefendingCustomNodeGroup = 'SelfDefendingCustomNodeGroup',
+    StringArrayCustomNodeGroup = 'StringArrayCustomNodeGroup'
 }

+ 3 - 0
src/enums/custom-nodes/DeadCodeInjectionCustomNode.ts

@@ -0,0 +1,3 @@
+export enum DeadCodeInjectionCustomNode {
+    BlockStatementDeadCodeInjectionNode = 'BlockStatementDeadCodeInjectionNode'
+}

+ 2 - 0
src/enums/logger/LoggingMessage.ts

@@ -7,6 +7,8 @@ export enum LoggingMessage {
     StageAnalyzingASTTree = 'Stage: analyzing AST-tree...',
     StageControlFlowFlattening = 'Stage: control flow flattening...',
     StageDeadCodeInjection = 'Stage: dead code injection...',
+    StagePostObfuscation = 'Stage: post-obfuscation...',
+    StagePreObfuscation = 'Stage: pre-obfuscation...',
     StageObfuscation = 'Stage: obfuscation...',
     Version = 'Version: %s'
 }

+ 20 - 18
src/enums/node-transformers/NodeTransformer.ts

@@ -1,20 +1,22 @@
 export enum NodeTransformer {
-    BlockStatementControlFlowTransformer,
-    CallExpressionTransformer,
-    ClassDeclarationTransformer,
-    CommentsTransformer,
-    DeadCodeInjectionTransformer,
-    FunctionControlFlowTransformer,
-    CatchClauseTransformer,
-    FunctionDeclarationTransformer,
-    FunctionTransformer,
-    LabeledStatementTransformer,
-    LiteralTransformer,
-    MemberExpressionTransformer,
-    MethodDefinitionTransformer,
-    ObfuscatingGuardsTransformer,
-    ObjectExpressionTransformer,
-    ParentificationTransformer,
-    TemplateLiteralTransformer,
-    VariableDeclarationTransformer
+    AstToEvalCallExpressionTransformer = 'AstToEvalCallExpressionTransformer',
+    BlockStatementControlFlowTransformer = 'BlockStatementControlFlowTransformer',
+    ClassDeclarationTransformer = 'ClassDeclarationTransformer',
+    CommentsTransformer = 'CommentsTransformer',
+    DeadCodeInjectionTransformer = 'DeadCodeInjectionTransformer',
+    EvalCallExpressionToAstTransformer = 'EvalCallExpressionToAstTransformer',
+    FunctionControlFlowTransformer = 'FunctionControlFlowTransformer',
+    CatchClauseTransformer = 'CatchClauseTransformer',
+    FunctionDeclarationTransformer = 'FunctionDeclarationTransformer',
+    FunctionTransformer = 'FunctionTransformer',
+    LabeledStatementTransformer = 'LabeledStatementTransformer',
+    LiteralTransformer = 'LiteralTransformer',
+    MemberExpressionTransformer = 'MemberExpressionTransformer',
+    MethodDefinitionTransformer = 'MethodDefinitionTransformer',
+    ObfuscatingGuardsTransformer = 'ObfuscatingGuardsTransformer',
+    ObjectExpressionKeysTransformer = 'ObjectExpressionKeysTransformer',
+    ObjectExpressionTransformer = 'ObjectExpressionTransformer',
+    ParentificationTransformer = 'ParentificationTransformer',
+    TemplateLiteralTransformer = 'TemplateLiteralTransformer',
+    VariableDeclarationTransformer = 'VariableDeclarationTransformer'
 }

+ 4 - 4
src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/ControlFlowReplacer.ts

@@ -1,6 +1,6 @@
 export enum ControlFlowReplacer {
-    BinaryExpressionControlFlowReplacer,
-    CallExpressionControlFlowReplacer,
-    LogicalExpressionControlFlowReplacer,
-    StringLiteralControlFlowReplacer,
+    BinaryExpressionControlFlowReplacer = 'BinaryExpressionControlFlowReplacer',
+    CallExpressionControlFlowReplacer = 'CallExpressionControlFlowReplacer',
+    LogicalExpressionControlFlowReplacer = 'LogicalExpressionControlFlowReplacer',
+    StringLiteralControlFlowReplacer = 'StringLiteralControlFlowReplacer'
 }

+ 1 - 1
src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer.ts

@@ -1,3 +1,3 @@
 export enum IdentifierObfuscatingReplacer {
-    BaseIdentifierObfuscatingReplacer
+    BaseIdentifierObfuscatingReplacer = 'BaseIdentifierObfuscatingReplacer'
 }

+ 3 - 3
src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer.ts

@@ -1,5 +1,5 @@
 export enum LiteralObfuscatingReplacer {
-    BooleanLiteralObfuscatingReplacer,
-    NumberLiteralObfuscatingReplacer,
-    StringLiteralObfuscatingReplacer
+    BooleanLiteralObfuscatingReplacer = 'BooleanLiteralObfuscatingReplacer',
+    NumberLiteralObfuscatingReplacer = 'NumberLiteralObfuscatingReplacer',
+    StringLiteralObfuscatingReplacer = 'StringLiteralObfuscatingReplacer'
 }

+ 2 - 2
src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.ts

@@ -1,4 +1,4 @@
 export enum ObfuscatingGuard {
-    BlackListNodeGuard,
-    ConditionalCommentNodeGuard
+    BlackListNodeGuard = 'BlackListNodeGuard',
+    ConditionalCommentNodeGuard = 'ConditionalCommentNodeGuard'
 }

+ 2 - 0
src/enums/node/NodeType.ts

@@ -1,5 +1,6 @@
 export enum NodeType {
     ArrayExpression = 'ArrayExpression',
+    ArrayPattern = 'ArrayPattern',
     ArrowFunctionExpression = 'ArrowFunctionExpression',
     AssignmentExpression = 'AssignmentExpression',
     AssignmentPattern = 'AssignmentPattern',
@@ -25,6 +26,7 @@ export enum NodeType {
     ObjectPattern = 'ObjectPattern',
     Program = 'Program',
     Property = 'Property',
+    RestElement = 'RestElement',
     ReturnStatement = 'ReturnStatement',
     Super = 'Super',
     SwitchCase = 'SwitchCase',

+ 0 - 7
src/interfaces/IObfuscationResult.d.ts

@@ -1,13 +1,6 @@
-import * as ESTree from 'estree';
-
 import { IInitializable } from './IInitializable';
 
 export interface IObfuscationResult extends IInitializable {
-    /**
-     * @return {string}
-     */
-    getObfuscatedAst (): ESTree.Program;
-
     /**
      * @return {string}
      */

+ 2 - 2
src/interfaces/custom-nodes/ICustomNodeGroup.d.ts

@@ -1,4 +1,4 @@
-import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from './ICustomNode';
 import { IInitializable } from '../IInitializable';
@@ -12,7 +12,7 @@ export interface ICustomNodeGroup extends IInitializable {
      * @param blockScopeNode
      * @param stackTraceData
      */
-    appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void;
+    appendCustomNodes (blockScopeNode: TNodeWithBlockScope, stackTraceData: IStackTraceData[]): void;
 
     /**
      * @returns {ObfuscationEvent}

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

@@ -29,5 +29,6 @@ export interface IOptions {
     readonly stringArrayEncoding: TStringArrayEncoding;
     readonly stringArrayThreshold: number;
     readonly target: ObfuscationTarget;
+    readonly transformObjectKeys: boolean;
     readonly unicodeEscapeSequence: boolean;
 }

+ 1 - 4
src/interfaces/source-map/ISourceMapCorrector.d.ts

@@ -1,13 +1,10 @@
-import * as ESTree from 'estree';
-
 import { IObfuscationResult } from '../IObfuscationResult';
 
 export interface ISourceMapCorrector {
     /**
-     * @param {Program} obfuscatedAst
      * @param {string} obfuscatedCode
      * @param {string} sourceMap
      * @returns {IObfuscationResult}
      */
-    correct (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string): IObfuscationResult;
+    correct (obfuscatedCode: string, sourceMap: string): IObfuscationResult;
 }

+ 7 - 1
src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -5,6 +5,7 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TStatement } from '../../types/node/TStatement';
 
 import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
@@ -16,6 +17,7 @@ import { ControlFlowCustomNode } from '../../enums/custom-nodes/ControlFlowCusto
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
 export class BlockStatementControlFlowTransformer extends AbstractNodeTransformer {
@@ -134,6 +136,10 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
             originalKeysIndexesInShuffledArray
         );
 
-        return blockStatementControlFlowFlatteningCustomNode.getNode()[0];
+        const newBlockStatementNode: TStatement = blockStatementControlFlowFlatteningCustomNode.getNode()[0];
+
+        NodeUtils.parentizeNode(newBlockStatementNode, parentNode);
+
+        return newBlockStatementNode;
     }
 }

+ 9 - 9
src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -7,7 +7,7 @@ import * as ESTree from 'estree';
 import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowReplacerFactory } from '../../types/container/node-transformers/TControlFlowReplacerFactory';
 import { TControlFlowStorageFactory } from '../../types/container/node-transformers/TControlFlowStorageFactory';
-import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
 
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../interfaces/options/IOptions';
@@ -57,9 +57,9 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     private readonly visitedFunctionNodes: Set<ESTree.Function> = new Set();
 
     /**
-     * @type {Set<TNodeWithBlockStatement>}
+     * @type {Set<TNodeWithBlockScope>}
      */
-    private readonly hostNodesWithControlFlowNode: Set<TNodeWithBlockStatement> = new Set();
+    private readonly hostNodesWithControlFlowNode: Set<TNodeWithBlockScope> = new Set();
 
     /**
      * @type {TControlFlowReplacerFactory}
@@ -131,7 +131,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
             return functionNode;
         }
 
-        const hostNode: TNodeWithBlockStatement = this.getHostNode(functionNode.body);
+        const hostNode: TNodeWithBlockScope = this.getHostNode(functionNode.body);
         const controlFlowStorage: IStorage<ICustomNode> = this.getControlFlowStorage(hostNode);
 
         this.controlFlowData.set(hostNode, controlFlowStorage);
@@ -153,10 +153,10 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} hostNode
+     * @param {TNodeWithBlockScope} hostNode
      * @returns {IStorage<ICustomNode>}
      */
-    private getControlFlowStorage (hostNode: TNodeWithBlockStatement): IStorage<ICustomNode> {
+    private getControlFlowStorage (hostNode: TNodeWithBlockScope): IStorage<ICustomNode> {
         const controlFlowStorage: IStorage <ICustomNode> = this.controlFlowStorageFactory();
 
         if (this.controlFlowData.has(hostNode)) {
@@ -174,10 +174,10 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
 
     /**
      * @param {BlockStatement} functionNodeBody
-     * @returns {TNodeWithBlockStatement}
+     * @returns {TNodeWithBlockScope}
      */
-    private getHostNode (functionNodeBody: ESTree.BlockStatement): TNodeWithBlockStatement {
-        const blockScopesOfNode: TNodeWithBlockStatement[] = NodeUtils.getBlockScopesOfNode(functionNodeBody);
+    private getHostNode (functionNodeBody: ESTree.BlockStatement): TNodeWithBlockScope {
+        const blockScopesOfNode: TNodeWithBlockScope[] = NodeUtils.getBlockScopesOfNode(functionNodeBody);
 
         if (blockScopesOfNode.length === 1) {
             return functionNodeBody;

+ 56 - 0
src/node-transformers/converting-transformers/AstToEvalCallExpressionTransformer.ts

@@ -0,0 +1,56 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+import jsStringEscape = require('js-string-escape');
+
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
+
+import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { Nodes } from '../../node/Nodes';
+import { NodeUtils } from '../../node/NodeUtils';
+
+@injectable()
+export class AstToEvalCallExpressionTransformer extends AbstractNodeTransformer {
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(randomGenerator, options);
+    }
+
+    /**
+     * @return {IVisitor}
+     */
+    public getVisitor (): IVisitor {
+        return {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                if (parentNode && node.isEvalRoot) {
+                    return this.transformNode(node, parentNode);
+                }
+            }
+        };
+    }
+
+    /**
+     * @param {ExpressionStatement} node
+     * @param {Node} parentNode
+     * @returns {Node}
+     */
+    public transformNode (node: ESTree.Node, parentNode: ESTree.Node): ESTree.Node {
+        const code: string = NodeUtils.convertStructureToCode([node]);
+
+        return Nodes.getCallExpressionNode(
+            Nodes.getIdentifierNode('eval'),
+            [
+                Nodes.getLiteralNode(jsStringEscape(code))
+            ]
+        );
+    }
+}

+ 0 - 84
src/node-transformers/converting-transformers/CallExpressionTransformer.ts

@@ -1,84 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
-
-import * as ESTree from 'estree';
-
-import { IOptions } from '../../interfaces/options/IOptions';
-import { IJavaScriptObfuscator } from '../../interfaces/IJavaScriptObfsucator';
-import { IObfuscationResult } from '../../interfaces/IObfuscationResult';
-import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
-
-import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
-import { NodeGuards } from '../../node/NodeGuards';
-
-@injectable()
-export class CallExpressionTransformer extends AbstractNodeTransformer {
-    /**
-     * @type {IJavaScriptObfuscator}
-     */
-    private readonly javaScriptObfuscator: IJavaScriptObfuscator;
-
-    /**
-     * @param {IJavaScriptObfuscator} javaScriptObfuscator
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    constructor (
-        @inject(ServiceIdentifiers.IJavaScriptObfuscator) javaScriptObfuscator: IJavaScriptObfuscator,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(randomGenerator, options);
-
-        this.javaScriptObfuscator = javaScriptObfuscator;
-    }
-
-    /**
-     * @return {IVisitor}
-     */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isCallExpressionNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
-    }
-
-    /**
-     * @param {CallExpression} callExpressionNode
-     * @param {Node} parentNode
-     * @returns {Node}
-     */
-    public transformNode (callExpressionNode: ESTree.CallExpression, parentNode: ESTree.Node): ESTree.Node {
-        const callExpressionFirstArgument: ESTree.Expression | ESTree.SpreadElement = callExpressionNode.arguments[0];
-
-        if (
-            NodeGuards.isIdentifierNode(callExpressionNode.callee)
-            && callExpressionNode.callee.name === 'eval'
-            && callExpressionFirstArgument
-            && NodeGuards.isLiteralNode(callExpressionFirstArgument)
-        ) {
-            return this.transformEvalCallExpressionLiteralToAst(callExpressionFirstArgument);
-        }
-
-        return callExpressionNode;
-    }
-
-    /**
-     * @param {Literal} literalNode
-     * @returns {Node}
-     */
-    private transformEvalCallExpressionLiteralToAst (literalNode: ESTree.Literal): ESTree.Node {
-        if (typeof literalNode.value !== 'string') {
-            return literalNode;
-        }
-
-        const code: string = literalNode.value;
-        const obfuscationResult: IObfuscationResult = this.javaScriptObfuscator.obfuscate(code);
-
-        return obfuscationResult.getObfuscatedAst();
-    }
-}

+ 72 - 0
src/node-transformers/converting-transformers/EvaCallExpressionToAstTransformer.ts

@@ -0,0 +1,72 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TStatement } from '../../types/node/TStatement';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
+
+import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeGuards } from '../../node/NodeGuards';
+import { Nodes } from '../../node/Nodes';
+import { NodeUtils } from '../../node/NodeUtils';
+
+@injectable()
+export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer {
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(randomGenerator, options);
+    }
+
+    /**
+     * @return {IVisitor}
+     */
+    public getVisitor (): IVisitor {
+        return {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                if (
+                    parentNode
+                    && NodeGuards.isCallExpressionNode(node)
+                    && NodeGuards.isIdentifierNode(node.callee)
+                    && node.callee.name === 'eval'
+                ) {
+                    return this.transformNode(node, parentNode);
+                }
+            }
+        };
+    }
+
+    /**
+     * @param {CallExpression} callExpression
+     * @param {Node} parentNode
+     * @returns {Node}
+     */
+    public transformNode (callExpression: ESTree.CallExpression, parentNode: ESTree.Node): ESTree.Node {
+        const callExpressionFirstArgument: ESTree.Expression | ESTree.SpreadElement = callExpression.arguments[0];
+
+        if (!callExpressionFirstArgument || !NodeGuards.isLiteralNode(callExpressionFirstArgument)) {
+            return callExpression;
+        }
+
+        if (typeof callExpressionFirstArgument.value !== 'string') {
+            return callExpression;
+        }
+
+        const code: string = callExpressionFirstArgument.value;
+        const ast: TStatement[] = NodeUtils.convertCodeToStructure(code);
+        const programNode: ESTree.Program = Nodes.getProgramNode(ast);
+
+        programNode.isEvalRoot = true;
+
+        return programNode;
+    }
+}

+ 230 - 0
src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts

@@ -0,0 +1,230 @@
+import { inject, injectable } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TNodeWithScope } from '../../types/node/TNodeWithScope';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
+
+import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeAppender } from '../../node/NodeAppender';
+import { NodeGuards } from '../../node/NodeGuards';
+import { Nodes } from '../../node/Nodes';
+import { NodeUtils } from '../../node/NodeUtils';
+
+@injectable()
+export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
+    /**
+     * @type {Map<VariableDeclarator, TNodeWithScope>}
+     */
+    private cachedScopeNodesMap: Map <ESTree.VariableDeclarator, TNodeWithScope> = new Map();
+
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(randomGenerator, options);
+    }
+
+    /**
+     * @param {TNodeWithScope} scopeNode
+     * @param {ExpressionStatement[]} expressionStatements
+     * @param {Node} variableDeclarator
+     */
+    private static appendExpressionStatements (
+        scopeNode: TNodeWithScope,
+        expressionStatements: ESTree.ExpressionStatement[],
+        variableDeclarator: ESTree.Node
+    ): void {
+        const variableDeclaration: ESTree.Node | undefined = variableDeclarator.parentNode;
+
+        if (!variableDeclaration || !NodeGuards.isVariableDeclarationNode(variableDeclaration)) {
+            throw new Error('Cannot find variable declaration for variable declarator');
+        }
+
+        NodeAppender.insertNodeAfter(scopeNode, expressionStatements, variableDeclaration);
+    }
+
+    /**
+     * @param {Property[]} properties
+     * @param {number[]} removablePropertyIds
+     * @returns {Property[]}
+     */
+    private static filterObjectExpressionProperties (properties: ESTree.Property[], removablePropertyIds: number[]): ESTree.Property[] {
+        return properties.filter((property: ESTree.Property, index: number) => !removablePropertyIds.includes(index));
+    }
+
+    /**
+     * @return {IVisitor}
+     */
+    public getVisitor (): IVisitor {
+        return {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                if (
+                    this.options.transformObjectKeys
+                    && parentNode
+                    && NodeGuards.isObjectExpressionNode(node)
+                    && NodeGuards.isVariableDeclaratorNode(parentNode)
+                ) {
+                    return this.transformNode(node, parentNode);
+                }
+            }
+        };
+    }
+
+    /**
+     * replaces:
+     *     var object = {
+     *          foo: 1,
+     *          bar: 2
+     *     };
+     *
+     * on:
+     *     var object = {};
+     *     object['foo'] = 1;
+     *     object['bar'] = 2;
+     *
+     * @param {MemberExpression} objectExpressionNode
+     * @param {NodeGuards} variableDeclarator
+     * @returns {NodeGuards}
+     */
+    public transformNode (objectExpressionNode: ESTree.ObjectExpression, variableDeclarator: ESTree.VariableDeclarator): ESTree.Node {
+        // should pass only Expression nodes as MemberExpression.object value
+        if (!NodeGuards.isIdentifierNode(variableDeclarator.id)) {
+            return objectExpressionNode;
+        }
+
+        const scopeNode: TNodeWithScope | null = NodeUtils.getScopeOfNode(variableDeclarator);
+
+        if (!scopeNode || !NodeGuards.isNodeHasScope(scopeNode)) {
+            return objectExpressionNode;
+        }
+
+        this.cachedScopeNodesMap.set(variableDeclarator, scopeNode);
+
+        return this.transformObjectExpressionNode(
+            objectExpressionNode,
+            variableDeclarator.id,
+            variableDeclarator
+        );
+    }
+
+    /**
+     * @param {Property[]} properties
+     * @param {Expression} memberExpressionObject
+     * @param {VariableDeclarator} variableDeclarator
+     * @returns {[ExpressionStatement[] , number[]]}
+     */
+    private extractPropertiesToExpressionStatements (
+        properties: ESTree.Property[],
+        memberExpressionObject: ESTree.Expression,
+        variableDeclarator: ESTree.VariableDeclarator
+    ): [ESTree.ExpressionStatement[], number[]] {
+        const propertiesLength: number = properties.length;
+        const expressionStatements: ESTree.ExpressionStatement[] = [];
+        const removablePropertyIds: number[] = [];
+
+        for (let i: number = 0; i < propertiesLength; i++) {
+            const property: ESTree.Property = properties[i];
+            const propertyKey: ESTree.Expression = property.key;
+
+            // invalid property nodes
+            if (
+                NodeGuards.isObjectPatternNode(property.value)
+                || NodeGuards.isArrayPatternNode(property.value)
+                || NodeGuards.isAssignmentPatternNode(property.value)
+                || NodeGuards.isRestElementNode(property.value)
+            ) {
+                continue;
+            }
+
+            /**
+             * Stage 1: collecting property node key names
+             */
+            let propertyKeyName: string;
+
+            if (NodeGuards.isLiteralNode(propertyKey) && typeof propertyKey.value === 'string') {
+                propertyKeyName = propertyKey.value;
+            } else if (NodeGuards.isIdentifierNode(propertyKey)) {
+                propertyKeyName = propertyKey.name;
+            } else {
+                continue;
+            }
+
+            /**
+             * Stage 2: creating new expression statement node with member expression based on removed property
+             */
+            const shouldCreateLiteralNode: boolean = !property.computed
+                || (property.computed && NodeGuards.isLiteralNode(property.key));
+            const memberExpressionProperty: ESTree.Expression = shouldCreateLiteralNode
+                ? Nodes.getLiteralNode(propertyKeyName)
+                : Nodes.getIdentifierNode(propertyKeyName);
+            const memberExpressionNode: ESTree.MemberExpression = Nodes
+                .getMemberExpressionNode(memberExpressionObject, memberExpressionProperty, true);
+            const rightExpression: ESTree.Expression = property.value;
+            const expressionStatementNode: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(
+                Nodes.getAssignmentExpressionNode('=', memberExpressionNode, rightExpression)
+            );
+
+            /**
+             * Stage 3: recursively processing nested object expressions
+             */
+            if (NodeGuards.isObjectExpressionNode(property.value)) {
+                this.transformObjectExpressionNode(
+                    property.value,
+                    memberExpressionNode,
+                    variableDeclarator
+                );
+            }
+
+            /**
+             * Stage 4: filling arrays
+             */
+            expressionStatements.push(expressionStatementNode);
+            removablePropertyIds.push(i);
+        }
+
+        return [expressionStatements, removablePropertyIds];
+    }
+
+    /**
+     * @param {ObjectExpression} objectExpressionNode
+     * @param {Expression} memberExpressionObjectNode
+     * @param {VariableDeclarator} variableDeclarator
+     * @returns {Node}
+     */
+    private transformObjectExpressionNode (
+        objectExpressionNode: ESTree.ObjectExpression,
+        memberExpressionObjectNode: ESTree.Expression,
+        variableDeclarator: ESTree.VariableDeclarator
+    ): ESTree.Node {
+        const properties: ESTree.Property[] = objectExpressionNode.properties;
+
+        if (!properties.length) {
+            return objectExpressionNode;
+        }
+
+        const scopeNode: TNodeWithScope | undefined = this.cachedScopeNodesMap.get(variableDeclarator);
+
+        if (!scopeNode) {
+            return objectExpressionNode;
+        }
+
+        const [expressionStatements, removablePropertyIds]: [ESTree.ExpressionStatement[], number[]] = this
+            .extractPropertiesToExpressionStatements(properties, memberExpressionObjectNode, variableDeclarator);
+
+        objectExpressionNode.properties = ObjectExpressionKeysTransformer
+            .filterObjectExpressionProperties(properties, removablePropertyIds);
+        ObjectExpressionKeysTransformer
+            .appendExpressionStatements(scopeNode, expressionStatements, variableDeclarator);
+
+        return objectExpressionNode;
+    }
+}

+ 36 - 32
src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts

@@ -4,19 +4,21 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
-import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
+import { TDeadNodeInjectionCustomNodeFactory } from '../../types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory';
+import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
 
+import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { ITransformersRunner } from '../../interfaces/node-transformers/ITransformersRunner';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { DeadCodeInjectionCustomNode } from '../../enums/custom-nodes/DeadCodeInjectionCustomNode';
 import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
 import { NodeType } from '../../enums/node/NodeType';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -53,23 +55,32 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
      */
     private collectedBlockStatementsLength: number;
 
+    /**
+     * @type {TDeadNodeInjectionCustomNodeFactory}
+     */
+    private readonly deadCodeInjectionCustomNodeFactory: TDeadNodeInjectionCustomNodeFactory;
+
     /**
      * @type {ITransformersRunner}
      */
     private readonly transformersRunner: ITransformersRunner;
 
     /**
+     * @param {TControlFlowCustomNodeFactory} deadCodeInjectionCustomNodeFactory
      * @param {ITransformersRunner} transformersRunner
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     constructor (
+        @inject(ServiceIdentifiers.Factory__IDeadCodeInjectionCustomNode)
+            deadCodeInjectionCustomNodeFactory: TDeadNodeInjectionCustomNodeFactory,
         @inject(ServiceIdentifiers.ITransformersRunner) transformersRunner: ITransformersRunner,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(randomGenerator, options);
 
+        this.deadCodeInjectionCustomNodeFactory = deadCodeInjectionCustomNodeFactory;
         this.transformersRunner = transformersRunner;
     }
 
@@ -112,7 +123,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
         estraverse.traverse(programNode, {
             enter: (node: ESTree.Node): any => {
                 if (NodeGuards.isBlockStatementNode(node)) {
-                    this.collectBlockStatementNodes(node, this.collectedBlockStatements);
+                    this.collectBlockStatementNodes(node, this.collectedBlockStatements, parentNode);
                 }
             }
         });
@@ -138,7 +149,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
             return blockStatementNode;
         }
 
-        const blockScopeOfBlockStatementNode: TNodeWithBlockStatement = NodeUtils
+        const blockScopeOfBlockStatementNode: TNodeWithBlockScope = NodeUtils
             .getBlockScopesOfNode(blockStatementNode)[0];
 
         if (blockScopeOfBlockStatementNode.type === NodeType.Program) {
@@ -154,23 +165,25 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
             return blockStatementNode;
         }
 
-        return this.replaceBlockStatementNode(blockStatementNode, randomBlockStatementNode);
+        return this.replaceBlockStatementNode(blockStatementNode, randomBlockStatementNode, parentNode);
     }
 
     /**
      * @param {BlockStatement} blockStatementNode
      * @param {BlockStatement[]} collectedBlockStatements
+     * @param {Node} parentNode
      */
     private collectBlockStatementNodes (
         blockStatementNode: ESTree.BlockStatement,
-        collectedBlockStatements: ESTree.BlockStatement[]
+        collectedBlockStatements: ESTree.BlockStatement[],
+        parentNode: ESTree.Node
     ): void {
         let clonedBlockStatementNode: ESTree.BlockStatement = NodeUtils.clone(blockStatementNode),
             nestedBlockStatementsCount: number = 0,
             isValidBlockStatementNode: boolean = true;
 
         estraverse.replace(clonedBlockStatementNode, {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null): any => {
+            enter: (node: ESTree.Node): any => {
                 /**
                  * Count nested block statements in current block statement
                  */
@@ -202,6 +215,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
         /**
          * We should transform identifiers in the dead code block statement to avoid conflicts with original code
          */
+        NodeUtils.parentizeNode(clonedBlockStatementNode, parentNode);
         clonedBlockStatementNode = this.transformersRunner.transform(
             clonedBlockStatementNode,
             DeadCodeInjectionTransformer.transformersToRenameBlockScopeIdentifiers
@@ -213,36 +227,26 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
     /**
      * @param {BlockStatement} blockStatementNode
      * @param {BlockStatement} randomBlockStatementNode
+     * @param {Node} parentNode
      * @returns {BlockStatement}
      */
     private replaceBlockStatementNode (
         blockStatementNode: ESTree.BlockStatement,
-        randomBlockStatementNode: ESTree.BlockStatement
+        randomBlockStatementNode: ESTree.BlockStatement,
+        parentNode: ESTree.Node
     ): ESTree.BlockStatement {
-        const random1: boolean = this.randomGenerator.getMathRandom() > 0.5;
-        const random2: boolean = this.randomGenerator.getMathRandom() > 0.5;
-
-        const operator: ESTree.BinaryOperator = random1 ? '===' : '!==';
-        const leftString: string = this.randomGenerator.getRandomString(5);
-        const rightString: string = random2 ? leftString : this.randomGenerator.getRandomString(5);
-
-        const [consequent, alternate]: [ESTree.BlockStatement, ESTree.BlockStatement] = random1 === random2
-            ? [blockStatementNode, randomBlockStatementNode]
-            : [randomBlockStatementNode, blockStatementNode];
-
-        let newBlockStatementNode: ESTree.BlockStatement = Nodes.getBlockStatementNode([
-            Nodes.getIfStatementNode(
-                Nodes.getBinaryExpressionNode(
-                    operator,
-                    Nodes.getLiteralNode(leftString),
-                    Nodes.getLiteralNode(rightString)
-                ),
-                consequent,
-                alternate
-            )
-        ]);
-
-        newBlockStatementNode = NodeUtils.parentize(newBlockStatementNode);
+        const blockStatementDeadCodeInjectionCustomNode: ICustomNode = this.deadCodeInjectionCustomNodeFactory(
+            DeadCodeInjectionCustomNode.BlockStatementDeadCodeInjectionNode
+        );
+
+        blockStatementDeadCodeInjectionCustomNode.initialize(
+            blockStatementNode,
+            randomBlockStatementNode
+        );
+
+        const newBlockStatementNode: ESTree.BlockStatement = <ESTree.BlockStatement>blockStatementDeadCodeInjectionCustomNode.getNode()[0];
+
+        NodeUtils.parentizeNode(newBlockStatementNode, parentNode);
 
         return newBlockStatementNode;
     }

+ 6 - 6
src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts

@@ -5,7 +5,7 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
 import { TIdentifierObfuscatingReplacerFactory } from "../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory";
-import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
 
 import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer';
 import { IOptions } from '../../interfaces/options/IOptions';
@@ -78,7 +78,7 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
      */
     public transformNode (classDeclarationNode: ESTree.ClassDeclaration, parentNode: ESTree.Node): ESTree.Node {
         const nodeIdentifier: number = this.nodeIdentifier++;
-        const blockScopeNode: TNodeWithBlockStatement = NodeUtils
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils
             .getBlockScopesOfNode(classDeclarationNode)[0];
 
         if (!this.options.renameGlobals && blockScopeNode.type === NodeType.Program) {
@@ -106,10 +106,10 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {number} nodeIdentifier
      */
-    private replaceScopeCachedIdentifiers (blockScopeNode: TNodeWithBlockStatement, nodeIdentifier: number): void {
+    private replaceScopeCachedIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
         const cachedReplaceableIdentifiers: ESTree.Identifier[] = <ESTree.Identifier[]>this.replaceableIdentifiers.get(blockScopeNode);
 
         cachedReplaceableIdentifiers.forEach((replaceableIdentifier: ESTree.Identifier) => {
@@ -121,10 +121,10 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {number} nodeIdentifier
      */
-    private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockStatement, nodeIdentifier: number): void {
+    private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
         const storedReplaceableIdentifiers: ESTree.Identifier[] = [];
 
         estraverse.replace(blockScopeNode, {

+ 6 - 6
src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts

@@ -5,7 +5,7 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
 import { TIdentifierObfuscatingReplacerFactory } from "../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory";
-import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
 import { TReplaceableIdentifiers } from '../../types/node-transformers/TReplaceableIdentifiers';
 import { TReplaceableIdentifiersNames } from '../../types/node-transformers/TReplaceableIdentifiersNames';
 
@@ -80,7 +80,7 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
      */
     public transformNode (functionDeclarationNode: ESTree.FunctionDeclaration, parentNode: ESTree.Node): ESTree.Node {
         const nodeIdentifier: number = this.nodeIdentifier++;
-        const blockScopeNode: TNodeWithBlockStatement = NodeUtils
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils
             .getBlockScopesOfNode(functionDeclarationNode)[0];
 
         if (!this.options.renameGlobals && blockScopeNode.type === NodeType.Program) {
@@ -109,12 +109,12 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
 
     /**
      * @param {FunctionDeclaration} functionDeclarationNode
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {number} nodeIdentifier
      */
     private replaceScopeCachedIdentifiers (
         functionDeclarationNode: ESTree.FunctionDeclaration,
-        blockScopeNode: TNodeWithBlockStatement,
+        blockScopeNode: TNodeWithBlockScope,
         nodeIdentifier: number
     ): void {
         const cachedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames | undefined = this.replaceableIdentifiers.get(blockScopeNode);
@@ -142,10 +142,10 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {number} nodeIdentifier
      */
-    private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockStatement, nodeIdentifier: number): void {
+    private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
         const storedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames = new Map();
 
         estraverse.replace(blockScopeNode, {

+ 2 - 2
src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts

@@ -5,7 +5,7 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
 import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory';
-import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
 import { TReplaceableIdentifiers } from '../../types/node-transformers/TReplaceableIdentifiers';
 import { TReplaceableIdentifiersNames } from '../../types/node-transformers/TReplaceableIdentifiersNames';
 
@@ -80,7 +80,7 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
      * @returns {NodeGuards}
      */
     public transformNode (variableDeclarationNode: ESTree.VariableDeclaration, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockStatement = NodeUtils
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils
             .getBlockScopesOfNode(variableDeclarationNode)[0];
 
         if (!this.options.renameGlobals && blockScopeNode.type === NodeType.Program) {

+ 101 - 74
src/node/NodeAppender.ts

@@ -1,61 +1,59 @@
 import * as ESTree from 'estree';
 
-import { TNodeWithBlockStatement } from '../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../types/node/TNodeWithBlockScope';
 import { TStatement } from '../types/node/TStatement';
 
 import { IStackTraceData } from '../interfaces/analyzers/stack-trace-analyzer/IStackTraceData';
+import { TNodeWithScope } from '../types/node/TNodeWithScope';
+import { NodeGuards } from './NodeGuards';
 
-/**
- * This class appends node into a first deepest BlockStatement in order of function calls
- *
- * For example:
- *
- * function Foo () {
- *     var baz = function () {
- *
- *     }
- *
- *     baz();
- * }
- *
- * foo();
- *
- * Appends node into block statement of `baz` function expression.
- */
 export class NodeAppender {
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
-     * @param {TStatement[]} nodeBodyStatements
+     * @param {TNodeWithScope} scopeNode
+     * @param {TStatement[]} scopeStatements
      */
-    public static appendNode (
-        blockScopeNode: TNodeWithBlockStatement,
-        nodeBodyStatements: TStatement[]
-    ): void {
-        if (!NodeAppender.validateBodyStatements(nodeBodyStatements)) {
-            nodeBodyStatements = [];
+    public static appendNode (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): void {
+        if (!NodeAppender.validateScopeStatements(scopeStatements)) {
+            scopeStatements = [];
         }
 
-        nodeBodyStatements = NodeAppender.parentizeBodyStatementsBeforeAppend(blockScopeNode, nodeBodyStatements);
+        scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements);
 
-        blockScopeNode.body = [
-            ...blockScopeNode.body,
-            ...nodeBodyStatements
-        ];
+        NodeAppender.setScopeNodeStatements(scopeNode, [
+            ...NodeAppender.getScopeNodeStatements(scopeNode),
+            ...scopeStatements
+        ]);
     }
 
     /**
+     * Appends node into a first deepest BlockStatement in order of function calls
+     *
+     * For example:
+     *
+     * function Foo () {
+     *     var baz = function () {
+     *
+     *     }
+     *
+     *     baz();
+     * }
+     *
+     * foo();
+     *
+     * Appends node into block statement of `baz` function expression
+     *
      * @param {IStackTraceData[]} blockScopeStackTraceData
-     * @param {TNodeWithBlockStatement} blockScopeNode
+     * @param {TNodeWithBlockScope} blockScopeNode
      * @param {TStatement[]} nodeBodyStatements
      * @param {number} index
      */
     public static appendNodeToOptimalBlockScope (
         blockScopeStackTraceData: IStackTraceData[],
-        blockScopeNode: TNodeWithBlockStatement,
+        blockScopeNode: TNodeWithBlockScope,
         nodeBodyStatements: TStatement[],
         index: number = 0
     ): void {
-        let targetBlockScope: TNodeWithBlockStatement;
+        let targetBlockScope: TNodeWithBlockScope;
 
         if (!blockScopeStackTraceData.length) {
             targetBlockScope = blockScopeNode;
@@ -96,70 +94,99 @@ export class NodeAppender {
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
-     * @param {TStatement[]} nodeBodyStatements
+     * @param {TNodeWithScope} scopeNode
+     * @param {TStatement[]} scopeStatements
+     * @param {Node} targetStatement
+     */
+    public static insertNodeAfter (scopeNode: TNodeWithScope, scopeStatements: TStatement[], targetStatement: ESTree.Statement): void {
+        const indexInScopeStatement: number = NodeAppender
+            .getScopeNodeStatements(scopeNode)
+            .indexOf(targetStatement);
+
+        NodeAppender.insertNodeAtIndex(scopeNode, scopeStatements, indexInScopeStatement + 1);
+    }
+
+    /**
+     * @param {TNodeWithScope} scopeNode
+     * @param {TStatement[]} scopeStatements
      * @param {number} index
      */
-    public static insertNodeAtIndex (
-        blockScopeNode: TNodeWithBlockStatement,
-        nodeBodyStatements: TStatement[],
-        index: number
-    ): void {
-        if (!NodeAppender.validateBodyStatements(nodeBodyStatements)) {
-            nodeBodyStatements = [];
+    public static insertNodeAtIndex (scopeNode: TNodeWithScope, scopeStatements: TStatement[], index: number): void {
+        if (!NodeAppender.validateScopeStatements(scopeStatements)) {
+            scopeStatements = [];
         }
 
-        nodeBodyStatements = NodeAppender.parentizeBodyStatementsBeforeAppend(blockScopeNode, nodeBodyStatements);
+        scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements);
 
-        blockScopeNode.body = [
-            ...blockScopeNode.body.slice(0, index),
-            ...nodeBodyStatements,
-            ...blockScopeNode.body.slice(index)
-        ];
+        NodeAppender.setScopeNodeStatements(scopeNode, [
+            ...NodeAppender.getScopeNodeStatements(scopeNode).slice(0, index),
+            ...scopeStatements,
+            ...NodeAppender.getScopeNodeStatements(scopeNode).slice(index)
+        ]);
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
-     * @param {TStatement[]} nodeBodyStatements
+     * @param {TNodeWithScope} scopeNode
+     * @param {TStatement[]} scopeStatements
      */
-    public static prependNode (
-        blockScopeNode: TNodeWithBlockStatement,
-        nodeBodyStatements: TStatement[]
-    ): void {
-        if (!NodeAppender.validateBodyStatements(nodeBodyStatements)) {
-            nodeBodyStatements = [];
+    public static prependNode (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): void {
+        if (!NodeAppender.validateScopeStatements(scopeStatements)) {
+            scopeStatements = [];
         }
 
-        nodeBodyStatements = NodeAppender.parentizeBodyStatementsBeforeAppend(blockScopeNode, nodeBodyStatements);
+        scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements);
 
-        blockScopeNode.body = [
-            ...nodeBodyStatements,
-            ...blockScopeNode.body,
-        ];
+        NodeAppender.setScopeNodeStatements(scopeNode, [
+            ...scopeStatements,
+            ...NodeAppender.getScopeNodeStatements(scopeNode),
+        ]);
     }
 
     /**
-     * @param {TNodeWithBlockStatement} blockScopeNode
-     * @param {TStatement[]} nodeBodyStatements
+     * @param {TNodeWithScope} scopeNode
+     * @returns {TStatement[]}
+     */
+    private static getScopeNodeStatements (scopeNode: TNodeWithScope): TStatement[] {
+        if (NodeGuards.isSwitchCaseNode(scopeNode)) {
+            return scopeNode.consequent;
+        }
+
+        return scopeNode.body;
+    }
+
+    /**
+     * @param {TNodeWithScope} scopeNode
+     * @param {TStatement[]} scopeStatements
      * @returns {TStatement[]}
      */
-    private static parentizeBodyStatementsBeforeAppend (
-        blockScopeNode: TNodeWithBlockStatement,
-        nodeBodyStatements: TStatement[]
-    ): TStatement[] {
-        nodeBodyStatements.forEach((statement: TStatement) => {
-            statement.parentNode = blockScopeNode;
+    private static parentizeScopeStatementsBeforeAppend (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): TStatement[] {
+        scopeStatements.forEach((statement: TStatement) => {
+            statement.parentNode = scopeNode;
         });
 
-        return nodeBodyStatements;
+        return scopeStatements;
     }
 
     /**
-     * @param {TStatement[]} nodeBodyStatements
+     * @param {TNodeWithScope} scopeNode
+     * @param {TStatement[]} statements
+     */
+    private static setScopeNodeStatements (scopeNode: TNodeWithScope, statements: TStatement[]): void {
+        if (NodeGuards.isSwitchCaseNode(scopeNode)) {
+            scopeNode.consequent = <ESTree.Statement[]>statements;
+
+            return;
+        }
+
+        scopeNode.body = statements;
+    }
+
+    /**
+     * @param {TStatement[]} scopeStatement
      * @returns {boolean}
      */
-    private static validateBodyStatements (nodeBodyStatements: TStatement[]): boolean {
-        return nodeBodyStatements.every((statementNode: TStatement) => {
+    private static validateScopeStatements (scopeStatement: TStatement[]): boolean {
+        return scopeStatement.every((statementNode: TStatement) => {
             return !!statementNode && statementNode.hasOwnProperty('type');
         });
     }

+ 53 - 4
src/node/NodeGuards.ts

@@ -1,10 +1,29 @@
 import * as ESTree from 'estree';
 
-import { TNodeWithBlockStatement } from '../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../types/node/TNodeWithBlockScope';
+import { TNodeWithScope } from '../types/node/TNodeWithScope';
 
 import { NodeType } from '../enums/node/NodeType';
 
 export class NodeGuards {
+    /**
+     * @type {string[]}
+     */
+    private static readonly nodesWithBlockScope: string[] = [
+        NodeType.ArrowFunctionExpression,
+        NodeType.FunctionDeclaration,
+        NodeType.FunctionExpression,
+        NodeType.MethodDefinition,
+    ];
+
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    public static isArrayPatternNode (node: ESTree.Node): node is ESTree.ArrayPattern {
+        return node.type === NodeType.ArrayPattern;
+    }
+
     /**
      * @param {Node} node
      * @returns {boolean}
@@ -170,12 +189,26 @@ export class NodeGuards {
         return object && !object.type !== undefined;
     }
 
+    /**
+     * @param {Node} node
+     * @param {Node} parentNode
+     * @returns {boolean}
+     */
+    public static isNodeHasBlockScope (node: ESTree.Node, parentNode: ESTree.Node): node is TNodeWithBlockScope {
+        return NodeGuards.isProgramNode(node) || (
+            NodeGuards.isBlockStatementNode(node)
+            && NodeGuards.nodesWithBlockScope.includes(parentNode.type)
+        );
+    }
+
     /**
      * @param {Node} node
      * @returns {boolean}
      */
-    public static isNodeHasBlockStatement (node: ESTree.Node): node is TNodeWithBlockStatement {
-        return Array.isArray((<TNodeWithBlockStatement>node).body);
+    public static isNodeHasScope (node: ESTree.Node): node is TNodeWithScope {
+        return NodeGuards.isProgramNode(node)
+            || NodeGuards.isBlockStatementNode(node)
+            || NodeGuards.isSwitchCaseNode(node);
     }
 
     /**
@@ -233,7 +266,7 @@ export class NodeGuards {
             parentNode.key === node;
         const parentNodeIsMemberExpressionNode: boolean = (
             NodeGuards.isMemberExpressionNode(parentNode) &&
-            parentNode.computed === false &&
+            !parentNode.computed &&
             parentNode.property === node
         );
         const parentNodeIsMethodDefinitionNode: boolean = NodeGuards.isMethodDefinitionNode(parentNode) &&
@@ -246,6 +279,14 @@ export class NodeGuards {
             !isLabelIdentifierNode;
     }
 
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    public static isRestElementNode (node: ESTree.Node): node is ESTree.RestElement {
+        return node.type === NodeType.RestElement;
+    }
+
     /**
      * @param {Node} node
      * @returns {boolean}
@@ -262,6 +303,14 @@ export class NodeGuards {
         return node.type === NodeType.Super;
     }
 
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    public static isSwitchCaseNode (node: ESTree.Node): node is ESTree.SwitchCase {
+        return node.type === NodeType.SwitchCase;
+    }
+
     /**
      * @param {Node} node
      * @returns {boolean}

+ 89 - 110
src/node/NodeUtils.ts

@@ -3,26 +3,14 @@ import * as esprima from 'esprima';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
-import { TNodeWithBlockStatement } from '../types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../types/node/TNodeWithBlockScope';
+import { TNodeWithScope } from '../types/node/TNodeWithScope';
 import { TObject } from '../types/TObject';
 import { TStatement } from '../types/node/TStatement';
 
-import { NodeType } from '../enums/node/NodeType';
-
 import { NodeGuards } from './NodeGuards';
 
 export class NodeUtils {
-    /**
-     * @type {string[]}
-     */
-    private static readonly nodesWithBlockScope: string[] = [
-        NodeType.ArrowFunctionExpression,
-        NodeType.FunctionDeclaration,
-        NodeType.FunctionExpression,
-        NodeType.MethodDefinition,
-        NodeType.Program
-    ];
-
     /**
      * @param {T} astTree
      * @returns {T}
@@ -47,45 +35,7 @@ export class NodeUtils {
      * @returns {T}
      */
     public static clone <T extends ESTree.Node = ESTree.Node> (astTree: T): T {
-        /**
-         * @param {T} node
-         * @returns {T}
-         */
-        const cloneRecursive: (node: T) => T = (node: T) => {
-            if (node === null) {
-                return node;
-            }
-
-            const copy: TObject = {};
-
-            Object
-                .keys(node)
-                .forEach((property: string): void => {
-                    if (property === 'parentNode') {
-                        return;
-                    }
-
-                    const value: any = (<TObject>node)[property];
-
-                    let clonedValue: any | null;
-
-                    if (value === null || value instanceof RegExp) {
-                        clonedValue = value;
-                    } else if (Array.isArray(value)) {
-                        clonedValue = value.map(cloneRecursive);
-                    } else if (typeof value === 'object') {
-                        clonedValue = cloneRecursive(value);
-                    } else {
-                        clonedValue = value;
-                    }
-
-                    copy[property] = clonedValue;
-                });
-
-            return <T>copy;
-        };
-
-        return NodeUtils.parentize(cloneRecursive(astTree));
+        return NodeUtils.parentize(NodeUtils.cloneRecursive(astTree));
     }
 
     /**
@@ -114,76 +64,29 @@ export class NodeUtils {
     }
 
     /**
-     * @param {NodeGuards} node
-     * @param {number} index
-     * @returns {NodeGuards}
+     * @param {Node} targetNode
+     * @returns {TNodeWithBlockScope[]}
      */
-    public static getBlockStatementNodeByIndex (node: ESTree.Node, index: number = 0): ESTree.Node {
-        if (!NodeGuards.isNodeHasBlockStatement(node)) {
-            throw new TypeError('The specified node have no a block-statement');
-        }
-
-        if (node.body[index] === undefined) {
-            throw new ReferenceError(`Wrong index \`${index}\`. Block-statement body length is \`${node.body.length}\``);
-        }
-
-        return node.body[index];
-    }
-
-    /**
-     * @param {NodeGuards} node
-     * @param {TNodeWithBlockStatement[]} blockScopes
-     * @returns {TNodeWithBlockStatement[]}
-     */
-    public static getBlockScopesOfNode (node: ESTree.Node, blockScopes: TNodeWithBlockStatement[] = []): TNodeWithBlockStatement[] {
-        const parentNode: ESTree.Node | undefined = node.parentNode;
-
-        if (!parentNode) {
-            throw new ReferenceError('`parentNode` property of given node is `undefined`');
-        }
-
-        if (NodeGuards.isBlockStatementNode(parentNode)) {
-            if (!parentNode.parentNode) {
-                throw new ReferenceError('`parentNode` property of `parentNode` of given node is `undefined`');
-            }
-
-            if (NodeUtils.nodesWithBlockScope.includes(parentNode.parentNode.type)) {
-                blockScopes.push(parentNode);
-            }
-        }
-
-        if (node !== parentNode) {
-            return NodeUtils.getBlockScopesOfNode(parentNode, blockScopes);
-        }
-
-        if (NodeGuards.isNodeHasBlockStatement(parentNode)) {
-            blockScopes.push(parentNode);
-        }
-
-        return blockScopes;
+    public static getBlockScopesOfNode (targetNode: ESTree.Node): TNodeWithBlockScope[] {
+        return NodeUtils.getBlockScopesOfNodeRecursive(targetNode);
     }
 
     /**
      * @param {NodeGuards} node
-     * @param {number} depth
-     * @returns {number}
+     * @returns {TNodeWithScope}
      */
-    public static getNodeBlockScopeDepth (node: ESTree.Node, depth: number = 0): number {
+    public static getScopeOfNode (node: ESTree.Node): TNodeWithScope {
         const parentNode: ESTree.Node | undefined = node.parentNode;
 
         if (!parentNode) {
             throw new ReferenceError('`parentNode` property of given node is `undefined`');
         }
 
-        if (NodeGuards.isProgramNode(parentNode)) {
-            return depth;
-        }
-
-        if (NodeGuards.isBlockStatementNode(node) && NodeUtils.nodesWithBlockScope.includes(parentNode.type)) {
-            return NodeUtils.getNodeBlockScopeDepth(parentNode, ++depth);
+        if (!NodeGuards.isNodeHasScope(parentNode)) {
+            return NodeUtils.getScopeOfNode(parentNode);
         }
 
-        return NodeUtils.getNodeBlockScopeDepth(parentNode, depth);
+        return parentNode;
     }
 
     /**
@@ -203,7 +106,7 @@ export class NodeUtils {
      * @returns {T}
      */
     public static parentize <T extends ESTree.Node = ESTree.Node> (astTree: T): T {
-        estraverse.traverse(astTree, {
+        estraverse.replace(astTree, {
             enter: NodeUtils.parentizeNode
         });
 
@@ -221,4 +124,80 @@ export class NodeUtils {
 
         return node;
     }
+
+    /**
+     * @param {T} node
+     * @returns {T}
+     */
+    private static cloneRecursive <T> (node: T): T {
+        if (node === null) {
+            return node;
+        }
+
+        const copy: TObject = {};
+
+        Object
+            .keys(node)
+            .forEach((property: string): void => {
+                if (property === 'parentNode') {
+                    return;
+                }
+
+                const value: any = (<TObject>node)[property];
+
+                let clonedValue: any | null;
+
+                if (value === null || value instanceof RegExp) {
+                    clonedValue = value;
+                } else if (Array.isArray(value)) {
+                    clonedValue = value.map(NodeUtils.cloneRecursive);
+                } else if (typeof value === 'object') {
+                    clonedValue = NodeUtils.cloneRecursive(value);
+                } else {
+                    clonedValue = value;
+                }
+
+                copy[property] = clonedValue;
+            });
+
+        return <T>copy;
+    }
+
+    /**
+     * @param {Node} node
+     * @param {TNodeWithBlockScope[]} blockScopes
+     * @param {number} depth
+     * @returns {TNodeWithBlockScope[]}
+     */
+    private static getBlockScopesOfNodeRecursive (
+        node: ESTree.Node,
+        blockScopes: TNodeWithBlockScope[] = [],
+        depth: number = 0
+    ): TNodeWithBlockScope[] {
+        const parentNode: ESTree.Node | undefined = node.parentNode;
+
+        if (!parentNode) {
+            throw new ReferenceError('`parentNode` property of given node is `undefined`');
+        }
+
+        if (
+            /**
+             * we can add program node instantly
+             */
+            NodeGuards.isProgramNode(node) ||
+            /**
+             * we shouldn't add to the array input node that is node with block scope itself
+             * so, on depth 0 we will skip push to the array of block scopes
+             */
+            (depth && NodeGuards.isNodeHasBlockScope(node, parentNode))
+        ) {
+            blockScopes.push(node);
+        }
+
+        if (node !== parentNode) {
+            return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, blockScopes, ++depth);
+        }
+
+        return blockScopes;
+    }
 }

+ 24 - 0
src/node/Nodes.ts

@@ -305,6 +305,30 @@ export class Nodes {
         };
     }
 
+    /**
+     * @param {Expression} key
+     * @param {FunctionExpression} value
+     * @param {"constructor" | "method" | "get" | "set"} kind
+     * @param {boolean} computed
+     * @returns {MethodDefinition}
+     */
+    public static getMethodDefinitionNode (
+        key: ESTree.Expression,
+        value: ESTree.FunctionExpression,
+        kind: 'constructor' | 'method' | 'get' | 'set',
+        computed: boolean,
+    ): ESTree.MethodDefinition {
+        return {
+            type: NodeType.MethodDefinition,
+            key,
+            value,
+            kind,
+            computed,
+            static: false,
+            obfuscatedNode: false
+        };
+    }
+
     /**
      * @param {Property[]} properties
      * @returns {ObjectExpression}

+ 6 - 0
src/options/Options.ts

@@ -206,6 +206,12 @@ export class Options implements IOptions {
     @IsIn([ObfuscationTarget.Browser, ObfuscationTarget.Extension, ObfuscationTarget.Node])
     public readonly target: ObfuscationTarget;
 
+    /**
+     * @type {boolean}
+     */
+    @IsBoolean()
+    public readonly transformObjectKeys: boolean;
+
     /**
      * @type {boolean}
      */

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

@@ -30,5 +30,6 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
     stringArrayEncoding: false,
     stringArrayThreshold: 0.75,
     target: ObfuscationTarget.Browser,
+    transformObjectKeys: false,
     unicodeEscapeSequence: false
 });

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

@@ -4,7 +4,7 @@ import { IdentifierNamesGenerator } from '../../enums/generators/identifier-name
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { SourceMapMode } from '../../enums/source-map/SourceMapMode';
 
-export const NO_CUSTOM_NODES_PRESET: TInputOptions = Object.freeze({
+export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
     compact: true,
     controlFlowFlattening: false,
     controlFlowFlatteningThreshold: 0,
@@ -29,5 +29,6 @@ export const NO_CUSTOM_NODES_PRESET: TInputOptions = Object.freeze({
     stringArrayEncoding: false,
     stringArrayThreshold: 0,
     target: ObfuscationTarget.Browser,
+    transformObjectKeys: false,
     unicodeEscapeSequence: false
 });

+ 1 - 5
src/source-map/SourceMapCorrector.ts

@@ -1,8 +1,6 @@
 import { inject, injectable } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
-import * as ESTree from 'estree';
-
 import { TObfuscationResultFactory } from '../types/container/TObfuscationResultFactory';
 
 import { ICryptUtils } from '../interfaces/utils/ICryptUtils';
@@ -45,14 +43,12 @@ export class SourceMapCorrector implements ISourceMapCorrector {
     }
 
     /**
-     * @param {Program} obfuscatedAst
      * @param {string} obfuscatedCode
      * @param {string} sourceMap
      * @returns {IObfuscationResult}
      */
-    public correct (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string): IObfuscationResult {
+    public correct (obfuscatedCode: string, sourceMap: string): IObfuscationResult {
         return this.obfuscationResultFactory(
-            obfuscatedAst,
             this.correctObfuscatedCode(obfuscatedCode, sourceMap),
             sourceMap
         );

+ 1 - 3
src/types/container/TObfuscationResultFactory.d.ts

@@ -1,5 +1,3 @@
-import * as ESTree from 'estree';
-
 import { IObfuscationResult } from '../../interfaces/IObfuscationResult';
 
-export type TObfuscationResultFactory = (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string) => IObfuscationResult;
+export type TObfuscationResultFactory = (obfuscatedCode: string, sourceMap: string) => IObfuscationResult;

+ 5 - 0
src/types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory.d.ts

@@ -0,0 +1,5 @@
+import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+
+import { DeadCodeInjectionCustomNode } from '../../../enums/custom-nodes/DeadCodeInjectionCustomNode';
+
+export type TDeadNodeInjectionCustomNodeFactory = (deadCodeInjectionCustomNodeName: DeadCodeInjectionCustomNode) => ICustomNode;

+ 3 - 0
src/types/node/TNodeWithBlockScope.d.ts

@@ -0,0 +1,3 @@
+import * as ESTree from 'estree';
+
+export type TNodeWithBlockScope = ESTree.Program | ESTree.BlockStatement;

+ 0 - 3
src/types/node/TNodeWithBlockStatement.d.ts

@@ -1,3 +0,0 @@
-import * as ESTree from 'estree';
-
-export type TNodeWithBlockStatement = ESTree.BlockStatement | ESTree.Program;

+ 3 - 0
src/types/node/TNodeWithScope.d.ts

@@ -0,0 +1,3 @@
+import * as ESTree from 'estree';
+
+export type TNodeWithScope = ESTree.Program | ESTree.BlockStatement | ESTree.SwitchCase;

+ 6 - 3
test/dev/dev.ts

@@ -1,5 +1,5 @@
 'use strict';
-import { NO_CUSTOM_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
 
 (function () {
     const JavaScriptObfuscator: any = require('../../index');
@@ -8,15 +8,18 @@ import { NO_CUSTOM_NODES_PRESET } from '../../src/options/presets/NoCustomNodes'
         `
         (function(){
             function foo (bar) {
-                eval('console.log(bar);');
+                eval('console.log(bar, \\'baz\\');');
+                console.log(eval('bar; console.log(\\'bark\\')'));
             }
             
             foo(1);
         })();
         `,
         {
-            ...NO_CUSTOM_NODES_PRESET,
+            ...NO_ADDITIONAL_NODES_PRESET,
             compact: false,
+            stringArray: true,
+            stringArrayThreshold: 1
         }
     ).getObfuscatedCode();
 

+ 11 - 11
test/functional-tests/analyzers/stack-trace-analyzer/StackTraceAnalyzer.spec.ts

@@ -7,7 +7,7 @@ import * as ESTree from 'estree';
 
 import { assert } from 'chai';
 
-import { TNodeWithBlockStatement } from '../../../../src/types/node/TNodeWithBlockStatement';
+import { TNodeWithBlockScope } from '../../../../src/types/node/TNodeWithBlockScope';
 
 import { IInversifyContainerFacade } from '../../../../src/interfaces/container/IInversifyContainerFacade';
 import { IStackTraceAnalyzer } from '../../../../src/interfaces/analyzers/stack-trace-analyzer/IStackTraceAnalyzer';
@@ -165,7 +165,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #1: basic-1', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/basic-1.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -215,7 +215,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #2: basic-2', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/basic-2.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -254,7 +254,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #3: deep conditions nesting', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/deep-conditions-nesting.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -293,7 +293,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #4: call before declaration', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/call-before-declaration.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -316,7 +316,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #5: call expression of object member #1', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/call-expression-of-object-member-1.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -375,7 +375,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #5: call expression of object member #2', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/call-expression-of-object-member-2.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -403,7 +403,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #6: no call expressions', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/no-call-expressions.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -420,7 +420,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #7: only call expression', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/only-call-expression.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -437,7 +437,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #8: self-invoking functions', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/self-invoking-functions.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 
@@ -472,7 +472,7 @@ describe('StackTraceAnalyzer', () => {
         describe('variant #9: no recursion', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/no-recursion.js');
-                const astTree: TNodeWithBlockStatement = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 

+ 3 - 3
test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
@@ -21,7 +21,7 @@ describe('ConsoleOutputDisableExpressionNode', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     disableConsoleOutput: true
                 }
             );
@@ -50,7 +50,7 @@ describe('ConsoleOutputDisableExpressionNode', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     disableConsoleOutput: false
                 }
             );

+ 3 - 3
test/functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
@@ -19,7 +19,7 @@ describe('DomainLockNode', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     domainLock: ['.example.com']
                 }
             );
@@ -40,7 +40,7 @@ describe('DomainLockNode', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     domainLock: []
                 }
             );

+ 3 - 3
test/functional-tests/custom-nodes/string-array-nodes/StringArrayCallsWrapper.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
@@ -20,7 +20,7 @@ describe('StringArrayCallsWrapper', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
                 }
@@ -43,7 +43,7 @@ describe('StringArrayCallsWrapper', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: false
                 }
             );

+ 3 - 3
test/functional-tests/custom-nodes/string-array-nodes/StringArrayNode.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
@@ -20,7 +20,7 @@ describe('StringArrayNode', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
                 }
@@ -43,7 +43,7 @@ describe('StringArrayNode', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: false
                 }
             );

+ 3 - 3
test/functional-tests/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
@@ -20,7 +20,7 @@ describe('StringArrayRotateFunctionNode', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     rotateStringArray: true,
                     stringArray: true,
                     stringArrayThreshold: 1
@@ -44,7 +44,7 @@ describe('StringArrayRotateFunctionNode', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     rotateStringArray: false,
                     stringArray: true,
                     stringArrayThreshold: 1

+ 10 - 9
test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts

@@ -7,7 +7,7 @@ import { StringArrayEncoding } from '../../../src/enums/StringArrayEncoding';
 
 import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscatorFacade';
 
-import { NO_CUSTOM_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';
 
@@ -26,7 +26,7 @@ describe('JavaScriptObfuscator', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -91,7 +91,7 @@ describe('JavaScriptObfuscator', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             sourceMap: true
                         }
                     );
@@ -120,7 +120,7 @@ describe('JavaScriptObfuscator', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             sourceMap: true,
                             sourceMapMode: SourceMapMode.Inline
                         }
@@ -195,7 +195,7 @@ describe('JavaScriptObfuscator', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -217,7 +217,7 @@ describe('JavaScriptObfuscator', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -240,7 +240,7 @@ describe('JavaScriptObfuscator', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -269,7 +269,7 @@ describe('JavaScriptObfuscator', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -438,7 +438,7 @@ describe('JavaScriptObfuscator', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -494,6 +494,7 @@ describe('JavaScriptObfuscator', () => {
                         stringArray: true,
                         stringArrayEncoding: StringArrayEncoding.Rc4,
                         stringArrayThreshold: 1,
+                        transformObjectKeys: true,
                         unicodeEscapeSequence: false
                     }
                 );

+ 16 - 15
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
@@ -29,13 +29,14 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
                 );
 
                 obfuscatedCode = obfuscationResult.getObfuscatedCode();
+                console.log(obfuscatedCode);
             });
 
             describe('`console.log` statements', ()=> {
@@ -117,7 +118,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1,
                         unicodeEscapeSequence: false
@@ -208,7 +209,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -232,7 +233,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -256,7 +257,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -280,7 +281,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -304,7 +305,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -331,7 +332,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -360,7 +361,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -384,7 +385,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -411,7 +412,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -440,7 +441,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -471,7 +472,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code.repeat(samples),
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: controlFlowFlatteningThreshold,
                     }
@@ -513,7 +514,7 @@ describe('BlockStatementControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }

+ 3 - 3
test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../../helpers/readFileAsString';
 
@@ -22,7 +22,7 @@ describe('BinaryExpressionControlFlowReplacer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -64,7 +64,7 @@ describe('BinaryExpressionControlFlowReplacer', function () {
                     obfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }

+ 4 - 4
test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../../helpers/readFileAsString';
 
@@ -22,7 +22,7 @@ describe('CallExpressionControlFlowReplacer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -64,7 +64,7 @@ describe('CallExpressionControlFlowReplacer', function () {
                     obfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }
@@ -111,7 +111,7 @@ describe('CallExpressionControlFlowReplacer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }

+ 5 - 5
test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../../helpers/readFileAsString';
 
@@ -22,7 +22,7 @@ describe('LogicalExpressionControlFlowReplacer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -64,7 +64,7 @@ describe('LogicalExpressionControlFlowReplacer', function () {
                     obfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }
@@ -111,7 +111,7 @@ describe('LogicalExpressionControlFlowReplacer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -135,7 +135,7 @@ describe('LogicalExpressionControlFlowReplacer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: .1
                     }

+ 2 - 2
test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/StringLiteralControlFlowReplacer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../../helpers/readFileAsString';
 
@@ -20,7 +20,7 @@ describe('StringLiteralControlFlowReplacer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     controlFlowFlattening: true,
                     controlFlowFlatteningThreshold: 1
                 }

+ 9 - 9
test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -38,7 +38,7 @@ describe('FunctionControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -80,7 +80,7 @@ describe('FunctionControlFlowTransformer', function () {
                     obfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }
@@ -123,7 +123,7 @@ describe('FunctionControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -147,7 +147,7 @@ describe('FunctionControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 1
                     }
@@ -182,7 +182,7 @@ describe('FunctionControlFlowTransformer', function () {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }
@@ -211,7 +211,7 @@ describe('FunctionControlFlowTransformer', function () {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         controlFlowFlattening: true,
                         controlFlowFlatteningThreshold: 0
                     }
@@ -240,7 +240,7 @@ describe('FunctionControlFlowTransformer', function () {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }
@@ -264,7 +264,7 @@ describe('FunctionControlFlowTransformer', function () {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             controlFlowFlattening: true,
                             controlFlowFlatteningThreshold: 1
                         }

+ 5 - 5
test/functional-tests/node-transformers/converting-transformers/member-expression-transformer/MemberExpressionTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -20,7 +20,7 @@ describe('MemberExpressionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -43,7 +43,7 @@ describe('MemberExpressionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -74,7 +74,7 @@ describe('MemberExpressionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -102,7 +102,7 @@ describe('MemberExpressionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 

+ 4 - 4
test/functional-tests/node-transformers/converting-transformers/method-definition-transformer/MethodDefinitionTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -19,7 +19,7 @@ describe('MethodDefinitionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -42,7 +42,7 @@ describe('MethodDefinitionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
                 }
@@ -70,7 +70,7 @@ describe('MethodDefinitionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 

+ 319 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec.ts

@@ -0,0 +1,319 @@
+import { assert } from 'chai';
+
+import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
+
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+
+import { readFileAsString } from '../../../../helpers/readFileAsString';
+
+import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
+
+describe('ObjectExpressionKeysTransformer', () => {
+    const variableMatch: string = '_0x([a-f0-9]){4,6}';
+
+    describe('transformation of object keys', () => {
+        describe('variant #1: simple', () => {
+            const match: string = `` +
+                `var *${variableMatch} *= *{};` +
+                `${variableMatch}\\['foo'] *= *'bar';` +
+                `${variableMatch}\\['baz'] *= *'bark';` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/simple.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #2: nested objects #1', () => {
+            const match: string = `` +
+                `var *${variableMatch} *= *{};` +
+                `${variableMatch}\\['foo'] *= *'bar';` +
+                `${variableMatch}\\['inner'] *= *{};` +
+                `${variableMatch}\\['inner']\\['inner1'] *= *{};` +
+                `${variableMatch}\\['inner']\\['inner1']\\['baz'] *= *'bark';` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/nested-objects-1.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #3: nested objects #2', () => {
+            const match: string = `` +
+                `var *${variableMatch} *= *{};` +
+                `${variableMatch}\\['foo'] *= *'bar';` +
+                `${variableMatch}\\['inner'] *= *{};` +
+                `${variableMatch}\\['ball'] *= *'door';` +
+                `${variableMatch}\\['inner']\\['baz'] *= *'bark';` +
+                `${variableMatch}\\['inner']\\['inner1'] *= *{};` +
+                `${variableMatch}\\['inner']\\['cow'] *= *'bear';` +
+                `${variableMatch}\\['inner']\\['inner1']\\['hawk'] *= *'geek';` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/nested-objects-2.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #4: correct integration with control flow flattening object', () => {
+            const match: string = `` +
+                `var *${variableMatch} *= *{};` +
+                `${variableMatch}\\['\\w{5}'] *= *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *{` +
+                    `return *${variableMatch} *\\+ *${variableMatch};` +
+                `};` +
+                `var *${variableMatch} *= *${variableMatch}\\['\\w{5}']\\(0x1, *0x2\\);` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/integration-with-control-flow-flattening.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        controlFlowFlattening: true,
+                        controlFlowFlatteningThreshold: 1,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+    });
+
+    describe('correct placement of expression statements', () => {
+        describe('variant #1: if statement', () => {
+            const match: string = `` +
+                `if *\\(!!\\[]\\) *{` +
+                    `var *${variableMatch} *= *{};` +
+                    `${variableMatch}\\['foo'] *= *'bar';` +
+                `}` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/placement-inside-if-statement.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #2: try statement', () => {
+            const match: string = `` +
+                `try *{` +
+                    `var *${variableMatch} *= *{};` +
+                    `${variableMatch}\\['foo'] *= *'bar';` +
+                `} *catch *\\(${variableMatch}\\) *{` +
+                `}` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/placement-inside-try-statement.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #3: catch clause statement', () => {
+            const match: string = `` +
+                `try *{` +
+                `} *catch *\\(${variableMatch}\\) *{` +
+                    `var *${variableMatch} *= *{};` +
+                    `${variableMatch}\\['foo'] *= *'bar';` +
+                `}` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/placement-inside-catch-clause.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should correctly transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #4: switch catch statement', () => {
+            const match: string = `` +
+                `switch *\\(!!\\[]\\) *{` +
+                    `case *!!\\[]:` +
+                        `var *${variableMatch} *= *{};` +
+                        `${variableMatch}\\['foo'] *= *'bar';` +
+                `}` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/placement-inside-switch-case.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('should transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+    });
+
+    describe('Ignore transformation', () => {
+        describe('variant #1: disabled option', () => {
+            const match: string = `` +
+                `var *${variableMatch} *= *{` +
+                    `'foo': *'bar',` +
+                    `'baz': *'bark'` +
+                `}` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/simple.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('shouldn\'t transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('variant #2: variable declaration without initialization', () => {
+            const match: string = `` +
+                `var *${variableMatch};` +
+                `${variableMatch} *= *{` +
+                    `'foo': *'bar',` +
+                    `'baz': *'bark'` +
+                `}` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/variable-declaration-without-initialization.js');
+                const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                );
+
+                obfuscatedCode = obfuscationResult.getObfuscatedCode();
+            });
+
+            it('shouldn\'t transform object keys', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+    });
+});

+ 3 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/integration-with-control-flow-flattening.js

@@ -0,0 +1,3 @@
+(function () {
+    var variable = 1 + 2;
+})();

+ 10 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/nested-objects-1.js

@@ -0,0 +1,10 @@
+(function(){
+    var object = {
+        foo: 'bar',
+        inner: {
+            inner1: {
+                baz: 'bark'
+            }
+        }
+    };
+})();

+ 14 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/nested-objects-2.js

@@ -0,0 +1,14 @@
+(function(){
+    var object = {
+        foo: 'bar',
+        inner: {
+            baz: 'bark',
+            inner1: {
+                hawk: 'geek'
+            },
+            cow: 'bear',
+
+        },
+        ball: 'door',
+    };
+})();

+ 8 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-catch-clause.js

@@ -0,0 +1,8 @@
+(function(){
+    try {
+    } catch (e) {
+        var object = {
+            foo: 'bar'
+        };
+    }
+})();

+ 7 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-if-statement.js

@@ -0,0 +1,7 @@
+(function(){
+    if (true) {
+        var object = {
+            foo: 'bar'
+        };
+    }
+})();

+ 8 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-switch-case.js

@@ -0,0 +1,8 @@
+(function(){
+    switch (true) {
+        case true:
+            var object = {
+                foo: 'bar'
+            };
+    }
+})();

+ 7 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/placement-inside-try-statement.js

@@ -0,0 +1,7 @@
+(function(){
+    try {
+        var object = {
+            foo: 'bar'
+        };
+    } catch (e) {}
+})();

+ 6 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/simple.js

@@ -0,0 +1,6 @@
+(function(){
+    var object = {
+        foo: 'bar',
+        baz: 'bark'
+    };
+})();

+ 7 - 0
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declaration-without-initialization.js

@@ -0,0 +1,7 @@
+(function(){
+    var object;
+    object = {
+        foo: 'bar',
+        baz: 'bark'
+    };
+})();

+ 5 - 5
test/functional-tests/node-transformers/converting-transformers/template-literal-transformer/TemplateLiteralTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -15,7 +15,7 @@ describe('TemplateLiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     unicodeEscapeSequence: false
                 }
             );
@@ -30,7 +30,7 @@ describe('TemplateLiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     unicodeEscapeSequence: false
                 }
             );
@@ -45,7 +45,7 @@ describe('TemplateLiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     unicodeEscapeSequence: false
                 }
             );
@@ -60,7 +60,7 @@ describe('TemplateLiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     unicodeEscapeSequence: false
                 }
             );

+ 10 - 10
test/functional-tests/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
@@ -33,7 +33,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 1,
                         stringArray: true,
@@ -69,7 +69,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 1,
                         stringArray: true,
@@ -105,7 +105,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 0,
                         stringArray: true,
@@ -149,7 +149,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 1,
                         stringArray: true,
@@ -200,7 +200,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 1,
                         stringArray: true,
@@ -251,7 +251,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 1,
                         stringArray: true,
@@ -339,7 +339,7 @@ describe('DeadCodeInjectionTransformer', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             deadCodeInjection: true,
                             deadCodeInjectionThreshold: 1,
                             stringArray: true,
@@ -396,7 +396,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1,
                         deadCodeInjection: true,
@@ -422,7 +422,7 @@ describe('DeadCodeInjectionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         deadCodeInjection: true,
                         deadCodeInjectionThreshold: 1,
                         debugProtection: true

+ 3 - 3
test/functional-tests/node-transformers/obfuscating-transformers/catch-clause-transformer/CatchClauseTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
@@ -24,7 +24,7 @@ describe('CatchClauseTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -55,7 +55,7 @@ describe('CatchClauseTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 

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

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
@@ -24,7 +24,7 @@ describe('ClassDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -50,7 +50,7 @@ describe('ClassDeclarationTransformer', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET
+                            ...NO_ADDITIONAL_NODES_PRESET
                         }
                     );
 
@@ -77,7 +77,7 @@ describe('ClassDeclarationTransformer', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             renameGlobals: true
                         }
                     );

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

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
@@ -24,7 +24,7 @@ describe('FunctionDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -50,7 +50,7 @@ describe('FunctionDeclarationTransformer', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET
+                            ...NO_ADDITIONAL_NODES_PRESET
                         }
                     );
 
@@ -77,7 +77,7 @@ describe('FunctionDeclarationTransformer', () => {
                     const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                         code,
                         {
-                            ...NO_CUSTOM_NODES_PRESET,
+                            ...NO_ADDITIONAL_NODES_PRESET,
                             renameGlobals: true
                         }
                     );
@@ -108,7 +108,7 @@ describe('FunctionDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -135,7 +135,7 @@ describe('FunctionDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 

+ 8 - 8
test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/FunctionTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -24,7 +24,7 @@ describe('FunctionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -60,7 +60,7 @@ describe('FunctionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -87,7 +87,7 @@ describe('FunctionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -116,7 +116,7 @@ describe('FunctionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -148,7 +148,7 @@ describe('FunctionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -198,7 +198,7 @@ describe('FunctionTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -265,7 +265,7 @@ describe('FunctionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();

+ 2 - 2
test/functional-tests/node-transformers/obfuscating-transformers/labeled-statement-transformer/LabeledStatementTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
@@ -25,7 +25,7 @@ describe('LabeledStatementTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 

+ 15 - 15
test/functional-tests/node-transformers/obfuscating-transformers/literal-transformer/LiteralTransformer.spec.ts

@@ -5,7 +5,7 @@ import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationRe
 import { IdentifierNamesGenerator } from '../../../../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
 import { StringArrayEncoding } from '../../../../../src/enums/StringArrayEncoding';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -24,7 +24,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -52,7 +52,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -73,7 +73,7 @@ describe('LiteralTransformer', () => {
                 testFunc = () => JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -96,7 +96,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -124,7 +124,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         unicodeEscapeSequence: true
 
                     }
@@ -149,7 +149,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1,
                         unicodeEscapeSequence: true
@@ -178,7 +178,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
                     }
@@ -203,7 +203,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayEncoding: StringArrayEncoding.Base64,
                         stringArrayThreshold: 1
@@ -232,7 +232,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayEncoding: StringArrayEncoding.Rc4,
                         stringArrayThreshold: 1
@@ -263,7 +263,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     `${code}\n`.repeat(samples),
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: stringArrayThreshold
                     }
@@ -301,7 +301,7 @@ describe('LiteralTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1,
                         identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator
@@ -327,7 +327,7 @@ describe('LiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
                 }
@@ -351,7 +351,7 @@ describe('LiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
                 }
@@ -375,7 +375,7 @@ describe('LiteralTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
+                    ...NO_ADDITIONAL_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
                 }

+ 4 - 4
test/functional-tests/node-transformers/obfuscating-transformers/object-expression-transformer/ObjectExpressionTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -19,7 +19,7 @@ describe('ObjectExpressionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -41,7 +41,7 @@ describe('ObjectExpressionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -63,7 +63,7 @@ describe('ObjectExpressionTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 

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

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../../../helpers/readFileAsString';
@@ -21,7 +21,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -49,7 +49,7 @@ describe('VariableDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -76,7 +76,7 @@ describe('VariableDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET,
+                        ...NO_ADDITIONAL_NODES_PRESET,
                         renameGlobals: true
                     }
                 );
@@ -104,7 +104,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -126,7 +126,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -149,7 +149,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -183,7 +183,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
@@ -238,7 +238,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
@@ -286,7 +286,7 @@ describe('VariableDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -308,7 +308,7 @@ describe('VariableDeclarationTransformer', () => {
                 const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     code,
                     {
-                        ...NO_CUSTOM_NODES_PRESET
+                        ...NO_ADDITIONAL_NODES_PRESET
                     }
                 );
 
@@ -332,7 +332,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -363,7 +363,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -402,7 +402,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -424,7 +424,7 @@ describe('VariableDeclarationTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 

+ 7 - 7
test/functional-tests/node-transformers/preparing-transformers/comments-transformer/CommentsTransformer.spec.ts

@@ -2,7 +2,7 @@ import { assert } from 'chai';
 
 import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
 
-import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
 
 import { readFileAsString } from '../../../../helpers/readFileAsString';
 
@@ -19,7 +19,7 @@ describe('CommentsTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -41,7 +41,7 @@ describe('CommentsTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -63,7 +63,7 @@ describe('CommentsTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -92,7 +92,7 @@ describe('CommentsTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -112,7 +112,7 @@ describe('CommentsTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 
@@ -134,7 +134,7 @@ describe('CommentsTransformer', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code,
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_ADDITIONAL_NODES_PRESET
                 }
             );
 

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません