소스 검색

Merge pull request #221 from javascript-obfuscator/node-metadata

Node metadata
Timofey Kachalov 7 년 전
부모
커밋
712dfd4331
92개의 변경된 파일1352개의 추가작업 그리고 1035개의 파일을 삭제
  1. 1 1
      .babelrc
  2. 2 0
      CHANGELOG.md
  3. 3 3
      README.md
  4. 0 0
      dist/index.js
  5. 13 13
      package.json
  6. 2 2
      src/EsprimaFacade.ts
  7. 1 0
      src/JavaScriptObfuscator.ts
  8. 2 2
      src/cli/sanitizers/IdentifierNamesGeneratorSanitizer.ts
  9. 2 2
      src/cli/sanitizers/ObfuscatingTargetSanitizer.ts
  10. 2 2
      src/cli/sanitizers/SourceMapModeSanitizer.ts
  11. 5 0
      src/container/modules/node-transformers/PreparingTransformersModule.ts
  12. 1 1
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  13. 10 10
      src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts
  14. 25 25
      src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts
  15. 8 8
      src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts
  16. 10 10
      src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts
  17. 3 3
      src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts
  18. 6 6
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts
  19. 12 12
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts
  20. 6 6
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts
  21. 5 5
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts
  22. 6 6
      src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts
  23. 1 1
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts
  24. 1 1
      src/custom-nodes/domain-lock-nodes/DomainLockNode.ts
  25. 1 1
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  26. 5 5
      src/custom-nodes/string-array-nodes/StringArrayNode.ts
  27. 5 5
      src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts
  28. 28 5
      src/declarations/ESTree.d.ts
  29. 3 3
      src/decorators/Initializable.ts
  30. 1 1
      src/enums/ObfuscationTarget.ts
  31. 1 0
      src/enums/node-transformers/NodeTransformer.ts
  32. 2 3
      src/interfaces/node-transformers/control-flow-transformers/IControlFlowReplacer.d.ts
  33. 11 11
      src/interfaces/storages/IArrayStorage.d.ts
  34. 52 0
      src/interfaces/storages/IMapStorage.d.ts
  35. 2 1
      src/node-transformers/TransformersRunner.ts
  36. 13 12
      src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts
  37. 5 5
      src/node-transformers/control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts
  38. 3 3
      src/node-transformers/control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts
  39. 3 3
      src/node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts
  40. 3 3
      src/node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.ts
  41. 3 3
      src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts
  42. 2 6
      src/node-transformers/converting-transformers/MemberExpressionTransformer.ts
  43. 2 6
      src/node-transformers/converting-transformers/MethodDefinitionTransformer.ts
  44. 7 7
      src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts
  45. 5 5
      src/node-transformers/converting-transformers/TemplateLiteralTransformer.ts
  46. 4 4
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
  47. 3 1
      src/node-transformers/obfuscating-transformers/CatchClauseTransformer.ts
  48. 7 2
      src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts
  49. 7 2
      src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts
  50. 2 1
      src/node-transformers/obfuscating-transformers/FunctionTransformer.ts
  51. 2 1
      src/node-transformers/obfuscating-transformers/LiteralTransformer.ts
  52. 2 14
      src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts
  53. 7 2
      src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts
  54. 2 2
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/identifier-obfuscating-replacers/BaseIdentifierObfuscatingReplacer.ts
  55. 4 4
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/BooleanLiteralObfuscatingReplacer.ts
  56. 2 2
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/NumberLiteralObfuscatingReplacer.ts
  57. 16 14
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.ts
  58. 6 5
      src/node-transformers/preparing-transformers/CustomNodesTransformer.ts
  59. 7 9
      src/node-transformers/preparing-transformers/EvaCallExpressionTransformer.ts
  60. 68 0
      src/node-transformers/preparing-transformers/MetadataTransformer.ts
  61. 4 1
      src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts
  62. 77 74
      src/node/NodeFactory.ts
  63. 46 0
      src/node/NodeMetadata.ts
  64. 14 6
      src/node/NodeUtils.ts
  65. 1 1
      src/options/Options.ts
  66. 13 13
      src/storages/ArrayStorage.ts
  67. 18 18
      src/storages/MapStorage.ts
  68. 1 1
      src/storages/control-flow/ControlFlowStorage.ts
  69. 1 1
      src/storages/custom-node-group/CustomNodeGroupStorage.ts
  70. 0 5
      src/types/container/TInversifyContainerModuleFactory.d.ts
  71. 2 3
      src/types/container/node-transformers/TControlFlowStorageFactory.d.ts
  72. 0 6
      src/types/node-transformers/TNodeTransformer.d.ts
  73. 2 2
      src/types/storages/TControlFlowStorage.d.ts
  74. 2 2
      src/types/storages/TCustomNodeGroupStorage.d.ts
  75. 2 2
      src/types/storages/TStringArrayStorage.d.ts
  76. 1 1
      src/utils/Utils.ts
  77. 11 11
      test/functional-tests/analyzers/stack-trace-analyzer/StackTraceAnalyzer.spec.ts
  78. 1 1
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec.ts
  79. 1 1
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec.ts
  80. 1 1
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec.ts
  81. 1 1
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/StringLiteralControlFlowReplacer.spec.ts
  82. 1 1
      test/functional-tests/templates/debug-protection-nodes/DebugProtectionFunctionCallTemplate.spec.ts
  83. 1 0
      test/index.spec.ts
  84. 7 6
      test/unit-tests/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.spec.ts
  85. 2 2
      test/unit-tests/node/node-appender/NodeAppender.spec.ts
  86. 59 59
      test/unit-tests/node/node-guards/NodeGuards.spec.ts
  87. 103 0
      test/unit-tests/node/node-metadata/NodeMetadata.spec.ts
  88. 115 117
      test/unit-tests/node/node-utils/NodeUtils.spec.ts
  89. 18 17
      test/unit-tests/storages/ArrayStorage.spec.ts
  90. 22 22
      test/unit-tests/storages/MapStorage.spec.ts
  91. 1 0
      webpack.config.js
  92. 401 390
      yarn.lock

+ 1 - 1
.babelrc

@@ -11,6 +11,6 @@
     }]
   ],
   "plugins": [
-    "@babel/transform-runtime"
+    "@babel/plugin-transform-runtime"
   ]
 }

+ 2 - 0
CHANGELOG.md

@@ -3,9 +3,11 @@ Change Log
 v0.15.0
 ---
 * **Breaking change:** dropped `node@4` and `node@5` support.
+* **Breaking change:** renamed `extension` value of `target` option on `browser-no-eval`.
 * **New CLI option:** `exclude` allows to exclude specific files or directories from obfuscation.
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/217
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/210
+* Internal: refactoring of many things.
 
 v0.14.3
 ---

+ 3 - 3
README.md

@@ -333,7 +333,7 @@ Following options are available for the JS Obfuscator:
     --string-array <boolean>
     --string-array-encoding <boolean|string> [true, false, base64, rc4]
     --string-array-threshold <number>
-    --target <string> [browser, extension, node]
+    --target <string> [browser, browser-no-eval, node]
     --transform-object-keys <boolean>
     --unicode-escape-sequence <boolean>
 ```
@@ -721,11 +721,11 @@ Allows to set target environment for obfuscated code.
 
 Available values: 
 * `browser`;
-* `extension`;
+* `browser-no-eval`;
 * `node`.
 
 Currently output code for `browser` and `node` targets is identical.
-Output code for `extension` target is not using `eval`.
+Output code for `browser-no-eval` target is not using `eval`.
 
 ### `transformObjectKeys`
 Type: `boolean` Default: `false`

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/index.js


+ 13 - 13
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.15.0-dev.3",
+  "version": "0.15.0-dev.4",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -19,11 +19,11 @@
     "javascript-obfuscator": "./bin/javascript-obfuscator"
   },
   "dependencies": {
-    "@babel/runtime": "7.0.0-beta.40",
+    "@babel/runtime": "7.0.0-beta.42",
     "chalk": "2.3.2",
     "chance": "1.0.13",
-    "class-validator": "0.8.1",
-    "commander": "2.14.1",
+    "class-validator": "0.8.4",
+    "commander": "2.15.0",
     "escodegen-wallaby": "1.6.18",
     "esprima": "4.0.0",
     "estraverse": "4.2.0",
@@ -35,14 +35,15 @@
     "opencollective": "1.0.3",
     "pjson": "1.0.9",
     "reflect-metadata": "0.1.12",
-    "source-map-support": "0.5.3",
+    "source-map-support": "0.5.4",
     "string-template": "1.0.0",
     "tslib": "1.9.0"
   },
   "devDependencies": {
-    "@babel/core": "7.0.0-beta.40",
-    "@babel/plugin-transform-runtime": "7.0.0-beta.40",
-    "@babel/preset-env": "7.0.0-beta.40",
+    "@babel/cli": "7.0.0-beta.42",
+    "@babel/core": "7.0.0-beta.42",
+    "@babel/plugin-transform-runtime": "7.0.0-beta.42",
+    "@babel/preset-env": "7.0.0-beta.42",
     "@types/chai": "4.1.2",
     "@types/chance": "1.0.0",
     "@types/escodegen": "0.0.6",
@@ -53,13 +54,12 @@
     "@types/mkdirp": "0.5.2",
     "@types/mocha": "2.2.48",
     "@types/multimatch": "2.1.2",
-    "@types/node": "9.4.6",
+    "@types/node": "9.4.7",
     "@types/rimraf": "2.0.2",
     "@types/sinon": "4.3.0",
     "@types/string-template": "1.0.2",
     "@types/webpack-env": "1.13.5",
     "awesome-typescript-loader": "5.0.0-0",
-    "babel-cli": "7.0.0-beta.3",
     "babel-loader": "8.0.0-beta.2",
     "chai": "4.1.2",
     "coveralls": "3.0.0",
@@ -67,16 +67,16 @@
     "mocha": "5.0.4",
     "pre-commit": "1.2.2",
     "rimraf": "2.6.2",
-    "sinon": "4.4.2",
+    "sinon": "4.4.6",
     "threads": "0.10.1",
     "ts-node": "5.0.1",
     "tslint": "5.9.1",
     "tslint-eslint-rules": "5.1.0",
     "tslint-language-service": "0.9.8",
     "tslint-webpack-plugin": "1.2.0",
-    "typescript": "2.7.2",
+    "typescript": "2.8.0-rc",
     "webpack": "4.1.1",
-    "webpack-cli": "2.0.10",
+    "webpack-cli": "2.0.12",
     "webpack-node-externals": "1.6.0"
   },
   "repository": {

+ 2 - 2
src/EsprimaFacade.ts

@@ -26,11 +26,11 @@ export class EsprimaFacade {
         let lastMeta: esprima.NodeMeta | null = null;
 
         try {
-            return esprima.parseScript(input, config, (node: ESTree.Node, meta: any) => lastMeta = meta);
+            return esprima.parseScript(input, config, (node: ESTree.Node, meta: esprima.NodeMeta) => lastMeta = meta);
         } catch {}
 
         try {
-            return esprima.parseModule(input, config, (node: ESTree.Node, meta: any) => lastMeta = meta);
+            return esprima.parseModule(input, config, (node: ESTree.Node, meta: esprima.NodeMeta) => lastMeta = meta);
         } catch (error) {
             return EsprimaFacade.processParsingError(input, error.message, lastMeta);
         }

+ 1 - 0
src/JavaScriptObfuscator.ts

@@ -49,6 +49,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
         NodeTransformer.LabeledStatementTransformer,
         NodeTransformer.LiteralTransformer,
         NodeTransformer.MemberExpressionTransformer,
+        NodeTransformer.MetadataTransformer,
         NodeTransformer.MethodDefinitionTransformer,
         NodeTransformer.ObfuscatingGuardsTransformer,
         NodeTransformer.ObjectExpressionKeysTransformer,

+ 2 - 2
src/cli/sanitizers/IdentifierNamesGeneratorSanitizer.ts

@@ -9,8 +9,8 @@ import { IdentifierNamesGenerator } from '../../enums/generators/identifier-name
 export const IdentifierNamesGeneratorSanitizer: TCLISanitizer <string> = (value: string): string => {
     const isCorrectIdentifierNamesGenerator: boolean = Object
         .keys(IdentifierNamesGenerator)
-        .some((key: any): boolean => {
-            return IdentifierNamesGenerator[key] === value;
+        .some((key: string): boolean => {
+            return IdentifierNamesGenerator[<keyof typeof IdentifierNamesGenerator>key] === value;
         });
 
     if (!isCorrectIdentifierNamesGenerator) {

+ 2 - 2
src/cli/sanitizers/ObfuscatingTargetSanitizer.ts

@@ -9,8 +9,8 @@ import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 export const ObfuscationTargetSanitizer: TCLISanitizer <string> = (value: string): string => {
     const isCorrectTarget: boolean = Object
         .keys(ObfuscationTarget)
-        .some((key: any): boolean => {
-            return ObfuscationTarget[key] === value;
+        .some((key: string): boolean => {
+            return ObfuscationTarget[<keyof typeof ObfuscationTarget>key] === value;
         });
 
     if (!isCorrectTarget) {

+ 2 - 2
src/cli/sanitizers/SourceMapModeSanitizer.ts

@@ -9,8 +9,8 @@ import { SourceMapMode } from '../../enums/source-map/SourceMapMode';
 export const SourceMapModeSanitizer: TCLISanitizer <string> = (value: string): string => {
     const isCorrectSourceMapMode: boolean = Object
         .keys(SourceMapMode)
-        .some((key: any): boolean => {
-            return SourceMapMode[key] === value;
+        .some((key: string): boolean => {
+            return SourceMapMode[<keyof typeof SourceMapMode>key] === value;
         });
 
     if (!isCorrectSourceMapMode) {

+ 5 - 0
src/container/modules/node-transformers/PreparingTransformersModule.ts

@@ -13,6 +13,7 @@ import { CommentsTransformer } from '../../../node-transformers/preparing-transf
 import { ConditionalCommentObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ConditionalCommentObfuscatingGuard';
 import { CustomNodesTransformer } from '../../../node-transformers/preparing-transformers/CustomNodesTransformer';
 import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvaCallExpressionTransformer';
+import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer';
 import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer';
 import { ParentificationTransformer } from '../../../node-transformers/preparing-transformers/ParentificationTransformer';
 
@@ -30,6 +31,10 @@ export const preparingTransformersModule: interfaces.ContainerModule = new Conta
         .to(EvalCallExpressionTransformer)
         .whenTargetNamed(NodeTransformer.EvalCallExpressionTransformer);
 
+    bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
+        .to(MetadataTransformer)
+        .whenTargetNamed(NodeTransformer.MetadataTransformer);
+
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
         .to(ObfuscatingGuardsTransformer)
         .whenTargetNamed(NodeTransformer.ObfuscatingGuardsTransformer);

+ 1 - 1
src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts

@@ -59,7 +59,7 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
      * @returns {string}
      */
     protected getTemplate (): string {
-        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.Extension
+        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
 

+ 10 - 10
src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
-import { Nodes } from '../../node/Nodes';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -48,18 +48,18 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getFunctionExpressionNode(
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.functionExpressionNode(
                 [
-                    Nodes.getIdentifierNode('x'),
-                    Nodes.getIdentifierNode('y')
+                    NodeFactory.identifierNode('x'),
+                    NodeFactory.identifierNode('y')
                 ],
-                Nodes.getBlockStatementNode([
-                    Nodes.getReturnStatementNode(
-                        Nodes.getBinaryExpressionNode(
+                NodeFactory.blockStatementNode([
+                    NodeFactory.returnStatementNode(
+                        NodeFactory.binaryExpressionNode(
                             this.operator,
-                            Nodes.getIdentifierNode('x'),
-                            Nodes.getIdentifierNode('y')
+                            NodeFactory.identifierNode('x'),
+                            NodeFactory.identifierNode('y')
                         )
                     )
                 ])

+ 25 - 25
src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts

@@ -12,8 +12,8 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -71,36 +71,36 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
     protected getNodeStructure (): TStatement[] {
         const controllerIdentifierName: string = this.randomGenerator.getRandomString(6);
         const indexIdentifierName: string = this.randomGenerator.getRandomString(6);
-        const structure: ESTree.BlockStatement = Nodes.getBlockStatementNode([
-            Nodes.getVariableDeclarationNode([
-                Nodes.getVariableDeclaratorNode(
-                    Nodes.getIdentifierNode(controllerIdentifierName),
-                    Nodes.getCallExpressionNode(
-                        Nodes.getMemberExpressionNode(
-                            Nodes.getLiteralNode(
+        const structure: ESTree.BlockStatement = NodeFactory.blockStatementNode([
+            NodeFactory.variableDeclarationNode([
+                NodeFactory.variableDeclaratorNode(
+                    NodeFactory.identifierNode(controllerIdentifierName),
+                    NodeFactory.callExpressionNode(
+                        NodeFactory.memberExpressionNode(
+                            NodeFactory.literalNode(
                                 this.originalKeysIndexesInShuffledArray.join('|')
                             ),
-                            Nodes.getIdentifierNode('split')
+                            NodeFactory.identifierNode('split')
                         ),
                         [
-                            Nodes.getLiteralNode('|')
+                            NodeFactory.literalNode('|')
                         ]
                     )
                 ),
-                Nodes.getVariableDeclaratorNode(
-                    Nodes.getIdentifierNode(indexIdentifierName),
-                    Nodes.getLiteralNode(0)
+                NodeFactory.variableDeclaratorNode(
+                    NodeFactory.identifierNode(indexIdentifierName),
+                    NodeFactory.literalNode(0)
                 )
             ]),
-            Nodes.getWhileStatementNode(
-                Nodes.getLiteralNode(true),
-                Nodes.getBlockStatementNode([
-                    Nodes.getSwitchStatementNode(
-                        Nodes.getMemberExpressionNode(
-                            Nodes.getIdentifierNode(controllerIdentifierName),
-                            Nodes.getUpdateExpressionNode(
+            NodeFactory.whileStatementNode(
+                NodeFactory.literalNode(true),
+                NodeFactory.blockStatementNode([
+                    NodeFactory.switchStatementNode(
+                        NodeFactory.memberExpressionNode(
+                            NodeFactory.identifierNode(controllerIdentifierName),
+                            NodeFactory.updateExpressionNode(
                                 '++',
-                                Nodes.getIdentifierNode(indexIdentifierName)
+                                NodeFactory.identifierNode(indexIdentifierName)
                             ),
                             true
                         ),
@@ -113,16 +113,16 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
                              * to prevent `unreachable code after return statement` warnings
                              */
                             if (!NodeGuards.isReturnStatementNode(statement)) {
-                                consequent.push(Nodes.getContinueStatement());
+                                consequent.push(NodeFactory.continueStatement());
                             }
 
-                            return Nodes.getSwitchCaseNode(
-                                Nodes.getLiteralNode(String(index)),
+                            return NodeFactory.switchCaseNode(
+                                NodeFactory.literalNode(String(index)),
                                 consequent
                             );
                         })
                     ),
-                    Nodes.getBreakStatement()
+                    NodeFactory.breakStatement()
                 ])
             )
         ]);

+ 8 - 8
src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
-import { Nodes } from '../../node/Nodes';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -48,23 +48,23 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        const calleeIdentifier: ESTree.Identifier = Nodes.getIdentifierNode('callee');
+        const calleeIdentifier: ESTree.Identifier = NodeFactory.identifierNode('callee');
         const params: ESTree.Identifier[] = [];
         const argumentsLength: number = this.expressionArguments.length;
 
         for (let i: number = 0; i < argumentsLength; i++) {
-            params.push(Nodes.getIdentifierNode(`param${i + 1}`));
+            params.push(NodeFactory.identifierNode(`param${i + 1}`));
         }
 
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getFunctionExpressionNode(
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.functionExpressionNode(
                 [
                     calleeIdentifier,
                     ...params
                 ],
-                Nodes.getBlockStatementNode([
-                    Nodes.getReturnStatementNode(
-                        Nodes.getCallExpressionNode(
+                NodeFactory.blockStatementNode([
+                    NodeFactory.returnStatementNode(
+                        NodeFactory.callExpressionNode(
                             calleeIdentifier,
                             params
                         )

+ 10 - 10
src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
-import { Nodes } from '../../node/Nodes';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -48,18 +48,18 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getFunctionExpressionNode(
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.functionExpressionNode(
                 [
-                    Nodes.getIdentifierNode('x'),
-                    Nodes.getIdentifierNode('y')
+                    NodeFactory.identifierNode('x'),
+                    NodeFactory.identifierNode('y')
                 ],
-                Nodes.getBlockStatementNode([
-                    Nodes.getReturnStatementNode(
-                        Nodes.getLogicalExpressionNode(
+                NodeFactory.blockStatementNode([
+                    NodeFactory.returnStatementNode(
+                        NodeFactory.logicalExpressionNode(
                             this.operator,
-                            Nodes.getIdentifierNode('x'),
-                            Nodes.getIdentifierNode('y')
+                            NodeFactory.identifierNode('x'),
+                            NodeFactory.identifierNode('y')
                         )
                     )
                 ])

+ 3 - 3
src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts

@@ -10,7 +10,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
-import { Nodes } from '../../node/Nodes';
+import { NodeFactory } from '../../node/NodeFactory';
 
 @injectable()
 export class StringLiteralNode extends AbstractCustomNode {
@@ -45,8 +45,8 @@ export class StringLiteralNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getLiteralNode(this.literalValue)
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.literalNode(this.literalValue)
         );
 
         return [structure];

+ 6 - 6
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts

@@ -13,7 +13,7 @@ import { IRandomGenerator } from "../../../interfaces/utils/IRandomGenerator";
 import { initializable } from '../../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../../AbstractCustomNode';
-import { Nodes } from '../../../node/Nodes';
+import { NodeFactory } from '../../../node/NodeFactory';
 import { NodeUtils } from '../../../node/NodeUtils';
 
 @injectable()
@@ -75,11 +75,11 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
     }
 
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getCallExpressionNode(
-                Nodes.getMemberExpressionNode(
-                    Nodes.getIdentifierNode(this.controlFlowStorageName),
-                    Nodes.getIdentifierNode(this.controlFlowStorageKey)
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.callExpressionNode(
+                NodeFactory.memberExpressionNode(
+                    NodeFactory.identifierNode(this.controlFlowStorageName),
+                    NodeFactory.identifierNode(this.controlFlowStorageKey)
                 ),
                 [
                     this.callee,

+ 12 - 12
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts

@@ -3,28 +3,28 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { initializable } from '../../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../../AbstractCustomNode';
+import { NodeFactory } from '../../../node/NodeFactory';
 import { NodeGuards } from '../../../node/NodeGuards';
-import { Nodes } from '../../../node/Nodes';
 import { NodeUtils } from '../../../node/NodeUtils';
 
 @injectable()
 export class ControlFlowStorageNode extends AbstractCustomNode {
     /**
-     * @type {IStorage <ICustomNode>}
+     * @type {TControlFlowStorage}
      */
     @initializable()
-    private controlFlowStorage!: IStorage <ICustomNode>;
+    private controlFlowStorage!: TControlFlowStorage;
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
@@ -41,9 +41,9 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      */
-    public initialize (controlFlowStorage: IStorage <ICustomNode>): void {
+    public initialize (controlFlowStorage: TControlFlowStorage): void {
         this.controlFlowStorage = controlFlowStorage;
     }
 
@@ -60,16 +60,16 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
                     throw new Error('Function node for control flow storage object should be passed inside the `ExpressionStatement` node!');
                 }
 
-                return Nodes.getPropertyNode(
-                    Nodes.getIdentifierNode(key),
+                return NodeFactory.propertyNode(
+                    NodeFactory.identifierNode(key),
                     node.expression
                 );
             });
 
-        let structure: ESTree.Node = Nodes.getVariableDeclarationNode([
-            Nodes.getVariableDeclaratorNode(
-                Nodes.getIdentifierNode(this.controlFlowStorage.getStorageId()),
-                Nodes.getObjectExpressionNode(propertyNodes)
+        let structure: ESTree.Node = NodeFactory.variableDeclarationNode([
+            NodeFactory.variableDeclaratorNode(
+                NodeFactory.identifierNode(this.controlFlowStorage.getStorageId()),
+                NodeFactory.objectExpressionNode(propertyNodes)
             )
         ]);
 

+ 6 - 6
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../../AbstractCustomNode';
-import { Nodes } from '../../../node/Nodes';
+import { NodeFactory } from '../../../node/NodeFactory';
 import { NodeUtils } from '../../../node/NodeUtils';
 
 @injectable()
@@ -74,11 +74,11 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
     }
 
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getCallExpressionNode(
-                Nodes.getMemberExpressionNode(
-                    Nodes.getIdentifierNode(this.controlFlowStorageName),
-                    Nodes.getIdentifierNode(this.controlFlowStorageKey)
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.callExpressionNode(
+                NodeFactory.memberExpressionNode(
+                    NodeFactory.identifierNode(this.controlFlowStorageName),
+                    NodeFactory.identifierNode(this.controlFlowStorageKey)
                 ),
                 [
                     this.leftValue,

+ 5 - 5
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts

@@ -10,7 +10,7 @@ import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../../AbstractCustomNode';
-import { Nodes } from '../../../node/Nodes';
+import { NodeFactory } from '../../../node/NodeFactory';
 import { NodeUtils } from '../../../node/NodeUtils';
 
 @injectable()
@@ -54,10 +54,10 @@ export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode
     }
 
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = Nodes.getExpressionStatementNode(
-            Nodes.getMemberExpressionNode(
-                Nodes.getIdentifierNode(this.controlFlowStorageName),
-                Nodes.getIdentifierNode(this.controlFlowStorageKey)
+        const structure: TStatement = NodeFactory.expressionStatementNode(
+            NodeFactory.memberExpressionNode(
+                NodeFactory.identifierNode(this.controlFlowStorageName),
+                NodeFactory.identifierNode(this.controlFlowStorageKey)
             )
         );
 

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

@@ -12,7 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
-import { Nodes } from '../../node/Nodes';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -70,12 +70,12 @@ export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
             ? [this.blockStatementNode, this.deadCodeInjectionRootAstHostNode]
             : [this.deadCodeInjectionRootAstHostNode, this.blockStatementNode];
 
-        const structure: BlockStatement = Nodes.getBlockStatementNode([
-            Nodes.getIfStatementNode(
-                Nodes.getBinaryExpressionNode(
+        const structure: BlockStatement = NodeFactory.blockStatementNode([
+            NodeFactory.ifStatementNode(
+                NodeFactory.binaryExpressionNode(
                     operator,
-                    Nodes.getLiteralNode(leftString),
-                    Nodes.getLiteralNode(rightString)
+                    NodeFactory.literalNode(leftString),
+                    NodeFactory.literalNode(rightString)
                 ),
                 consequent,
                 alternate

+ 1 - 1
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts

@@ -60,7 +60,7 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
      * @returns {string}
      */
     protected getTemplate (): string {
-        const debuggerTemplate: string = this.options.target !== ObfuscationTarget.Extension
+        const debuggerTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? DebuggerTemplate()
             : DebuggerTemplateNoEval();
 

+ 1 - 1
src/custom-nodes/domain-lock-nodes/DomainLockNode.ts

@@ -74,7 +74,7 @@ export class DomainLockNode extends AbstractCustomNode {
             domainsString,
             domainsString.length * 3
         );
-        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.Extension
+        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
 

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

@@ -109,7 +109,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
      * @returns {string}
      */
     private getDecodeStringArrayTemplate (): string {
-        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.Extension
+        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
         const atobPolyfill: string = format(AtobTemplate(), { globalVariableTemplate });

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

@@ -5,10 +5,10 @@ import format from 'string-template';
 
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
+import { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../interfaces/storages/IStorage';
 
 import { initializable } from '../../decorators/Initializable';
 
@@ -21,10 +21,10 @@ import { StringArrayStorage } from '../../storages/string-array/StringArrayStora
 @injectable()
 export class StringArrayNode extends AbstractCustomNode {
     /**
-     * @type {IStorage <string>}
+     * @type {TStringArrayStorage}
      */
     @initializable()
-    private stringArrayStorage!: IStorage <string>;
+    private stringArrayStorage!: TStringArrayStorage;
 
     /**
      * @type {string}
@@ -53,12 +53,12 @@ export class StringArrayNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {IStorage<string>} stringArrayStorage
+     * @param {TStringArrayStorage} stringArrayStorage
      * @param {string} stringArrayName
      * @param {number} stringArrayRotateValue
      */
     public initialize (
-        stringArrayStorage: IStorage <string>,
+        stringArrayStorage: TStringArrayStorage,
         stringArrayName: string,
         stringArrayRotateValue: number
     ): void {

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

@@ -4,12 +4,12 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
+import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../../../interfaces/analyzers/stack-trace-analyzer/IStackTraceData';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -38,20 +38,20 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
     private readonly customNodeFactory: TCustomNodeFactory;
 
     /**
-     * @type {IStorage <string>}
+     * @type {TStringArrayStorage}
      */
-    private readonly stringArrayStorage: IStorage <string>;
+    private readonly stringArrayStorage: TStringArrayStorage;
 
     /**
      * @param {TCustomNodeFactory} customNodeFactory
-     * @param {IStorage<string>} stringArrayStorage
+     * @param {TStringArrayStorage} stringArrayStorage
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStorage<string>,
+        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,

+ 28 - 5
src/declarations/ESTree.d.ts

@@ -4,21 +4,44 @@ import * as escodegen from 'escodegen-wallaby';
 import * as ESTree from 'estree';
 
 declare module 'estree' {
-    interface BaseNode {
+    export interface BaseNodeMetadata {
         ignoredNode?: boolean;
-        obfuscatedNode?: boolean;
+    }
+
+    export interface IdentifierNodeMetadata extends BaseNodeMetadata {
+        renamedIdentifier?: boolean;
+    }
+
+    export interface LiteralNodeMetadata extends BaseNodeMetadata {
+        replacedLiteral?: boolean;
+    }
+
+    interface BaseNode {
+        metadata?: BaseNodeMetadata;
         parentNode?: ESTree.Node;
     }
 
-    interface ExpressionStatement extends ESTree.BaseStatement {
+    interface Identifier extends BaseNode {
+        metadata?: IdentifierNodeMetadata;
+    }
+
+    interface SimpleLiteral extends BaseNode {
+        metadata?: LiteralNodeMetadata;
+    }
+
+    interface RegExpLiteral extends BaseNode {
+        metadata?: LiteralNodeMetadata;
+    }
+
+    interface ExpressionStatement extends BaseNode {
         directive?: 'use strict';
     }
 
-    interface SimpleLiteral extends ESTree.BaseNode, ESTree.BaseExpression {
+    interface SimpleLiteral extends BaseNode {
         'x-verbatim-property'?: escodegen.XVerbatimProperty;
     }
 
-    interface RegExpLiteral extends ESTree.BaseNode, ESTree.BaseExpression {
+    interface RegExpLiteral extends BaseNode {
         'x-verbatim-property'?: escodegen.XVerbatimProperty;
     }
 }

+ 3 - 3
src/decorators/Initializable.ts

@@ -85,7 +85,7 @@ function wrapTargetMethodsInInitializedCheck (target: IInitializable, initialize
             return;
         }
 
-        const targetProperty: any = target[propertyName];
+        const targetProperty: IInitializable[keyof IInitializable] = target[propertyName];
 
         if (typeof targetProperty !== 'function') {
             return;
@@ -128,14 +128,14 @@ function wrapInitializeMethodInInitializeCheck (
 
     Object.defineProperty(target, initializeMethodName, {
         ...methodDescriptor,
-        value: function (): void {
+        value: function (): typeof originalMethod {
             /**
              * should define metadata before `initialize` method call,
              * because of cases when other methods will called inside `initialize` method
              */
             Reflect.defineMetadata(initializedTargetMetadataKey, true, this);
 
-            const result: any = originalMethod.apply(this, arguments);
+            const result: typeof originalMethod = originalMethod.apply(this, arguments);
 
             if (this[propertyKey]) {}
 

+ 1 - 1
src/enums/ObfuscationTarget.ts

@@ -1,5 +1,5 @@
 export enum ObfuscationTarget {
     Browser = 'browser',
-    Extension = 'extension',
+    BrowserNoEval = 'browser-no-eval',
     Node = 'node'
 }

+ 1 - 0
src/enums/node-transformers/NodeTransformer.ts

@@ -12,6 +12,7 @@ export enum NodeTransformer {
     LabeledStatementTransformer = 'LabeledStatementTransformer',
     LiteralTransformer = 'LiteralTransformer',
     MemberExpressionTransformer = 'MemberExpressionTransformer',
+    MetadataTransformer = 'MetadataTransformer',
     MethodDefinitionTransformer = 'MethodDefinitionTransformer',
     ObfuscatingGuardsTransformer = 'ObfuscatingGuardsTransformer',
     ObjectExpressionKeysTransformer = 'ObjectExpressionKeysTransformer',

+ 2 - 3
src/interfaces/node-transformers/control-flow-transformers/IControlFlowReplacer.d.ts

@@ -1,7 +1,6 @@
 import * as ESTree from 'estree';
 
-import { ICustomNode } from '../../custom-nodes/ICustomNode';
-import { IStorage } from '../../storages/IStorage';
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 
 export interface IControlFlowReplacer {
     /**
@@ -13,6 +12,6 @@ export interface IControlFlowReplacer {
     replace (
         node: ESTree.Node,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>
+        controlFlowStorage: TControlFlowStorage
     ): ESTree.Node;
 }

+ 11 - 11
src/interfaces/storages/IStorage.d.ts → src/interfaces/storages/IArrayStorage.d.ts

@@ -1,17 +1,17 @@
 import { IInitializable } from '../IInitializable';
 
-export interface IStorage <T> extends IInitializable {
+export interface IArrayStorage <V> extends IInitializable {
     /**
-     * @param key
-     * @returns T
+     * @param {number} key
+     * @returns {V}
      */
-    get (key: string | number): T;
+    get (key: number): V;
 
     /**
      * @param value
-     * @returns string | number | null
+     * @returns number | null
      */
-    getKeyOf (value: T): string | number | null;
+    getKeyOf (value: V): number | null;
 
     /**
      * @returns number
@@ -19,9 +19,9 @@ export interface IStorage <T> extends IInitializable {
     getLength (): number;
 
     /**
-     * @returns any
+     * @returns {V[]}
      */
-    getStorage (): any;
+    getStorage (): V[];
 
     /**
      * @returns string
@@ -40,10 +40,10 @@ export interface IStorage <T> extends IInitializable {
     mergeWith (storage: this, mergeId: boolean): void;
 
     /**
-     * @param key
-     * @param value
+     * @param {number} key
+     * @param {V} value
      */
-    set (key: string | number, value: T): void;
+    set (key: number, value: V): void;
 
     /**
      * @returns string

+ 52 - 0
src/interfaces/storages/IMapStorage.d.ts

@@ -0,0 +1,52 @@
+import { IInitializable } from '../IInitializable';
+
+export interface IMapStorage <K, V> extends IInitializable {
+    /**
+     * @param {K} key
+     * @returns {V}
+     */
+    get (key: K): V;
+
+    /**
+     * @param {V} value
+     * @returns {K | null}
+     */
+    getKeyOf (value: V): K | null;
+
+    /**
+     * @returns number
+     */
+    getLength (): number;
+
+    /**
+     * @returns {Map<K, V>}
+     */
+    getStorage (): Map <K, V>;
+
+    /**
+     * @returns string
+     */
+    getStorageId (): string;
+
+    /**
+     * @param args
+     */
+    initialize (...args: any[]): void;
+
+    /**
+     * @param storage
+     * @param mergeId
+     */
+    mergeWith (storage: this, mergeId: boolean): void;
+
+    /**
+     * @param {K} key
+     * @param {V} value
+     */
+    set (key: K, value: V): void;
+
+    /**
+     * @returns string
+     */
+    toString (): string;
+}

+ 2 - 1
src/node-transformers/TransformersRunner.ts

@@ -17,6 +17,7 @@ import { TransformationStage } from '../enums/node-transformers/TransformationSt
 import { VisitorDirection } from '../enums/node-transformers/VisitorDirection';
 
 import { NodeGuards } from '../node/NodeGuards';
+import { NodeMetadata } from '../node/NodeMetadata';
 
 @injectable()
 export class TransformersRunner implements ITransformersRunner {
@@ -96,7 +97,7 @@ export class TransformersRunner implements ITransformersRunner {
         }
 
         return (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-            if (node.ignoredNode) {
+            if (NodeMetadata.isIgnoredNode(node)) {
                 return estraverse.VisitorOption.Skip;
             }
 

+ 13 - 12
src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -6,13 +6,13 @@ import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowReplacerFactory } from '../../types/container/node-transformers/TControlFlowReplacerFactory';
+import { TControlFlowStorage } from '../../types/storages/TControlFlowStorage';
 import { TControlFlowStorageFactory } from '../../types/container/node-transformers/TControlFlowStorageFactory';
 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 { IStorage } from '../../interfaces/storages/IStorage';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { ControlFlowCustomNode } from '../../enums/custom-nodes/ControlFlowCustomNode';
@@ -21,8 +21,9 @@ import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
-import { NodeGuards } from '../../node/NodeGuards';
 import { NodeAppender } from '../../node/NodeAppender';
+import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -48,9 +49,9 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     private static readonly hostNodeSearchMaxDepth: number = 2;
 
     /**
-     * @type {Map<ESTree.Node, IStorage<ICustomNode>>}
+     * @type {Map<ESTree.Node, TControlFlowStorage>}
      */
-    private readonly controlFlowData: Map <ESTree.Node, IStorage<ICustomNode>> = new Map();
+    private readonly controlFlowData: Map <ESTree.Node, TControlFlowStorage> = new Map();
 
     /**
      * @type {Set<ESTree.Function>}
@@ -140,7 +141,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
         }
 
         const hostNode: TNodeWithBlockScope = this.getHostNode(functionNode.body);
-        const controlFlowStorage: IStorage<ICustomNode> = this.getControlFlowStorage(hostNode);
+        const controlFlowStorage: TControlFlowStorage = this.getControlFlowStorage(hostNode);
 
         this.controlFlowData.set(hostNode, controlFlowStorage);
         this.transformFunctionBody(functionNode.body, controlFlowStorage);
@@ -162,17 +163,17 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
 
     /**
      * @param {TNodeWithBlockScope} hostNode
-     * @returns {IStorage<ICustomNode>}
+     * @returns {TControlFlowStorage}
      */
-    private getControlFlowStorage (hostNode: TNodeWithBlockScope): IStorage<ICustomNode> {
-        const controlFlowStorage: IStorage <ICustomNode> = this.controlFlowStorageFactory();
+    private getControlFlowStorage (hostNode: TNodeWithBlockScope): TControlFlowStorage {
+        const controlFlowStorage: TControlFlowStorage = this.controlFlowStorageFactory();
 
         if (this.controlFlowData.has(hostNode)) {
             if (this.hostNodesWithControlFlowNode.has(hostNode)) {
                 hostNode.body.shift();
             }
 
-            const hostControlFlowStorage: IStorage<ICustomNode> = <IStorage<ICustomNode>>this.controlFlowData.get(hostNode);
+            const hostControlFlowStorage: TControlFlowStorage = <TControlFlowStorage>this.controlFlowData.get(hostNode);
 
             controlFlowStorage.mergeWith(hostControlFlowStorage, true);
         }
@@ -218,12 +219,12 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
 
     /**
      * @param {BlockStatement} functionNodeBody
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      */
-    private transformFunctionBody (functionNodeBody: ESTree.BlockStatement, controlFlowStorage: IStorage<ICustomNode>): void {
+    private transformFunctionBody (functionNodeBody: ESTree.BlockStatement, controlFlowStorage: TControlFlowStorage): void {
         estraverse.replace(functionNodeBody, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node | null): estraverse.VisitorOption | ESTree.Node => {
-                if (node.ignoredNode) {
+                if (NodeMetadata.isIgnoredNode(node)) {
                     return estraverse.VisitorOption.Skip;
                 }
 

+ 5 - 5
src/node-transformers/control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts

@@ -4,12 +4,12 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 
 import { IControlFlowReplacer } from '../../../interfaces/node-transformers/control-flow-transformers/IControlFlowReplacer';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 @injectable()
 export abstract class AbstractControlFlowReplacer implements IControlFlowReplacer {
@@ -72,21 +72,21 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
     /**
      * @param {Node} node
      * @param {Node} parentNode
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      * @returns {Node}
      */
-    public abstract replace (node: ESTree.Node, parentNode: ESTree.Node, controlFlowStorage: IStorage <ICustomNode>): ESTree.Node;
+    public abstract replace (node: ESTree.Node, parentNode: ESTree.Node, controlFlowStorage: TControlFlowStorage): ESTree.Node;
 
     /**
      * @param {ICustomNode} customNode
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      * @param {string} replacerId
      * @param {number} usingExistingIdentifierChance
      * @returns {string}
      */
     protected insertCustomNodeToControlFlowStorage (
         customNode: ICustomNode,
-        controlFlowStorage: IStorage <ICustomNode>,
+        controlFlowStorage: TControlFlowStorage,
         replacerId: string,
         usingExistingIdentifierChance: number
     ): string {

+ 3 - 3
src/node-transformers/control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts

@@ -4,11 +4,11 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
@@ -38,13 +38,13 @@ export class BinaryExpressionControlFlowReplacer extends ExpressionWithOperatorC
     /**
      * @param {BinaryExpression} binaryExpressionNode
      * @param {Node} parentNode
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      * @returns {Node}
      */
     public replace (
         binaryExpressionNode: ESTree.BinaryExpression,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>
+        controlFlowStorage: TControlFlowStorage
     ): ESTree.Node {
         const replacerId: string = binaryExpressionNode.operator;
         const binaryExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(

+ 3 - 3
src/node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts

@@ -4,12 +4,12 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
@@ -40,13 +40,13 @@ export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplac
     /**
      * @param {CallExpression} callExpressionNode
      * @param {NodeGuards} parentNode
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      * @returns {NodeGuards}
      */
     public replace (
         callExpressionNode: ESTree.CallExpression,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>
+        controlFlowStorage: TControlFlowStorage
     ): ESTree.Node {
         const callee: ESTree.Expression = <ESTree.Expression>callExpressionNode.callee;
 

+ 3 - 3
src/node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.ts

@@ -4,11 +4,11 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
@@ -40,13 +40,13 @@ export class LogicalExpressionControlFlowReplacer extends ExpressionWithOperator
     /**
      * @param {LogicalExpression} logicalExpressionNode
      * @param {NodeGuards} parentNode
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      * @returns {NodeGuards}
      */
     public replace (
         logicalExpressionNode: ESTree.LogicalExpression,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>
+        controlFlowStorage: TControlFlowStorage
     ): ESTree.Node {
         if (this.checkForProhibitedExpressions(logicalExpressionNode.left, logicalExpressionNode.right)) {
             return logicalExpressionNode;

+ 3 - 3
src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts

@@ -4,12 +4,12 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
@@ -40,13 +40,13 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
     /**
      * @param {Literal} literalNode
      * @param {NodeGuards} parentNode
-     * @param {IStorage<ICustomNode>} controlFlowStorage
+     * @param {TControlFlowStorage} controlFlowStorage
      * @returns {NodeGuards}
      */
     public replace (
         literalNode: ESTree.Literal,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>
+        controlFlowStorage: TControlFlowStorage
     ): ESTree.Node {
         if (NodeGuards.isPropertyNode(parentNode) && parentNode.key === literalNode) {
             return literalNode;

+ 2 - 6
src/node-transformers/converting-transformers/MemberExpressionTransformer.ts

@@ -7,10 +7,10 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
-import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
 
 @injectable()
@@ -69,11 +69,7 @@ export class MemberExpressionTransformer extends AbstractNodeTransformer {
             }
 
             memberExpressionNode.computed = true;
-            memberExpressionNode.property = {
-                type: NodeType.Literal,
-                value: memberExpressionNode.property.name,
-                raw: `'${memberExpressionNode.property.name}'`
-            };
+            memberExpressionNode.property = NodeFactory.literalNode(memberExpressionNode.property.name);
         }
 
         return memberExpressionNode;

+ 2 - 6
src/node-transformers/converting-transformers/MethodDefinitionTransformer.ts

@@ -7,10 +7,10 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
-import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
 
 /**
@@ -82,11 +82,7 @@ export class MethodDefinitionTransformer extends AbstractNodeTransformer {
             methodDefinitionNode.computed === false
         ) {
             methodDefinitionNode.computed = true;
-            methodDefinitionNode.key = {
-                type: NodeType.Literal,
-                value: methodDefinitionNode.key.name,
-                raw: `'${methodDefinitionNode.key.name}'`
-            };
+            methodDefinitionNode.key = NodeFactory.literalNode(methodDefinitionNode.key.name);
         }
 
         return methodDefinitionNode;

+ 7 - 7
src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts

@@ -13,8 +13,8 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeAppender } from '../../node/NodeAppender';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -191,12 +191,12 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
             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 expressionStatementNode: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(
-                Nodes.getAssignmentExpressionNode('=', memberExpressionNode, propertyValue)
+                ? NodeFactory.literalNode(propertyKeyName)
+                : NodeFactory.identifierNode(propertyKeyName);
+            const memberExpressionNode: ESTree.MemberExpression = NodeFactory
+                .memberExpressionNode(memberExpressionObject, memberExpressionProperty, true);
+            const expressionStatementNode: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(
+                NodeFactory.assignmentExpressionNode('=', memberExpressionNode, propertyValue)
             );
 
             /**

+ 5 - 5
src/node-transformers/converting-transformers/TemplateLiteralTransformer.ts

@@ -14,8 +14,8 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 /**
@@ -79,7 +79,7 @@ export class TemplateLiteralTransformer extends AbstractNodeTransformer {
         let nodes: ESTree.Expression[] = [];
 
         templateLiteralNode.quasis.forEach((templateElement: ESTree.TemplateElement) => {
-            nodes.push(Nodes.getLiteralNode(templateElement.value.cooked));
+            nodes.push(NodeFactory.literalNode(templateElement.value.cooked));
 
             const expression: ESTree.Expression | undefined = templateLiteralExpressions.shift();
 
@@ -100,18 +100,18 @@ export class TemplateLiteralTransformer extends AbstractNodeTransformer {
             !TemplateLiteralTransformer.isLiteralNodeWithStringValue(nodes[0]) &&
             !TemplateLiteralTransformer.isLiteralNodeWithStringValue(nodes[1])
         ) {
-            nodes.unshift(Nodes.getLiteralNode(''));
+            nodes.unshift(NodeFactory.literalNode(''));
         }
 
         if (nodes.length > 1) {
-            let root: ESTree.BinaryExpression = Nodes.getBinaryExpressionNode(
+            let root: ESTree.BinaryExpression = NodeFactory.binaryExpressionNode(
                 '+',
                 <ESTree.Literal>nodes.shift(),
                 <ESTree.Expression>nodes.shift()
             );
 
             nodes.forEach((node: ESTree.Literal | ESTree.Expression) => {
-                root = Nodes.getBinaryExpressionNode('+', root, <ESTree.Literal | ESTree.Expression>node);
+                root = NodeFactory.binaryExpressionNode('+', root, <ESTree.Literal | ESTree.Expression>node);
             });
 
             return root;

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

@@ -20,8 +20,8 @@ import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -128,7 +128,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
         }
 
         const slicedBody: ESTree.Statement[] = scopeBody.slice(0, indexInScope);
-        const hostBlockStatementNode: ESTree.BlockStatement = Nodes.getBlockStatementNode(slicedBody);
+        const hostBlockStatementNode: ESTree.BlockStatement = NodeFactory.blockStatementNode(slicedBody);
         const functionDeclarationName: string = targetNode.id.name;
 
         let isScopeHoistedFunctionDeclaration: boolean = false;
@@ -359,8 +359,8 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
          * with function declaration node. This function declaration node will create block scope for all identifiers
          * inside random block statement node and this identifiers won't affect identifiers of the rest AST tree.
          */
-        const deadCodeInjectionRootAstHostNode: ESTree.BlockStatement = Nodes.getBlockStatementNode([
-            Nodes.getFunctionDeclarationNode(
+        const deadCodeInjectionRootAstHostNode: ESTree.BlockStatement = NodeFactory.blockStatementNode([
+            NodeFactory.functionDeclarationNode(
                 DeadCodeInjectionTransformer.deadCodeInjectionRootAstHostNodeName,
                 [],
                 randomBlockStatementNode

+ 3 - 1
src/node-transformers/obfuscating-transformers/CatchClauseTransformer.ts

@@ -16,6 +16,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 
 /**
  * replaces:
@@ -108,7 +109,8 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
 
                     if (node.name !== newIdentifierName) {
                         node.name = newIdentifierName;
-                        node.obfuscatedNode = true;
+
+                        NodeMetadata.set(node, { renamedIdentifier: true });
                     }
                 }
             }

+ 7 - 2
src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts

@@ -18,6 +18,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 import { NodeUtils } from '../../node/NodeUtils';
 
 /**
@@ -146,14 +147,18 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
 
         estraverse.replace(blockScopeNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
-                if (parentNode && !node.obfuscatedNode && NodeGuards.isReplaceableIdentifierNode(node, parentNode)) {
+                if (
+                    parentNode
+                    && NodeGuards.isReplaceableIdentifierNode(node, parentNode)
+                    && !NodeMetadata.isRenamedIdentifier(node)
+                ) {
                     const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
                         .replace(node.name, nodeIdentifier);
                     const newIdentifierName: string = newIdentifier.name;
 
                     if (node.name !== newIdentifierName) {
                         node.name = newIdentifierName;
-                        node.obfuscatedNode = true;
+                        NodeMetadata.set(node, { renamedIdentifier: true });
                     } else {
                         storedReplaceableIdentifiers.push(node);
                     }

+ 7 - 2
src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts

@@ -20,6 +20,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 import { NodeUtils } from '../../node/NodeUtils';
 
 /**
@@ -167,14 +168,18 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
 
         estraverse.replace(blockScopeNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
-                if (parentNode && !node.obfuscatedNode && NodeGuards.isReplaceableIdentifierNode(node, parentNode)) {
+                if (
+                    parentNode
+                    && NodeGuards.isReplaceableIdentifierNode(node, parentNode)
+                    && !NodeMetadata.isRenamedIdentifier(node)
+                ) {
                     const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
                         .replace(node.name, nodeIdentifier);
                     const newIdentifierName: string = newIdentifier.name;
 
                     if (node.name !== newIdentifierName) {
                         node.name = newIdentifierName;
-                        node.obfuscatedNode = true;
+                        NodeMetadata.set(node, { renamedIdentifier: true });
                     } else {
                         const storedReplaceableIdentifiers: ESTree.Identifier[] = storedReplaceableIdentifiersNamesMap.get(node.name) || [];
 

+ 2 - 1
src/node-transformers/obfuscating-transformers/FunctionTransformer.ts

@@ -16,6 +16,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 
 /**
  * replaces:
@@ -157,7 +158,7 @@ export class FunctionTransformer extends AbstractNodeTransformer {
 
                     if (node.name !== newIdentifierName) {
                         node.name = newIdentifierName;
-                        node.obfuscatedNode = true;
+                        NodeMetadata.set(node, { renamedIdentifier: true });
                     }
                 }
             }

+ 2 - 1
src/node-transformers/obfuscating-transformers/LiteralTransformer.ts

@@ -14,6 +14,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 
 @injectable()
 export class LiteralTransformer extends AbstractNodeTransformer {
@@ -47,7 +48,7 @@ export class LiteralTransformer extends AbstractNodeTransformer {
             case TransformationStage.Obfuscating:
                 return {
                     enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                        if (parentNode && NodeGuards.isLiteralNode(node) && !node.obfuscatedNode) {
+                        if (parentNode && NodeGuards.isLiteralNode(node) && !NodeMetadata.isReplacedLiteral(node)) {
                             return this.transformNode(node, parentNode);
                         }
                     }

+ 2 - 14
src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts

@@ -7,10 +7,10 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
-import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
 
 /**
@@ -33,18 +33,6 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
         super(randomGenerator, options);
     }
 
-    /**
-     * @param {Identifier} node
-     * @returns {Literal}
-     */
-    private static transformIdentifierPropertyKey (node: ESTree.Identifier): ESTree.Literal {
-        return {
-            type: NodeType.Literal,
-            value: node.name,
-            raw: `'${node.name}'`
-        };
-    }
-
     /**
      * @param {TransformationStage} transformationStage
      * @returns {IVisitor | null}
@@ -82,7 +70,7 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
                 }
 
                 if (NodeGuards.isIdentifierNode(property.key)) {
-                    property.key = ObjectExpressionTransformer.transformIdentifierPropertyKey(property.key);
+                    property.key = NodeFactory.literalNode(property.key.name);
                 }
             });
 

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

@@ -20,6 +20,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
 import { NodeUtils } from '../../node/NodeUtils';
 
 /**
@@ -186,13 +187,17 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
 
         estraverse.replace(blockScopeNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
-                if (parentNode && !node.obfuscatedNode && NodeGuards.isReplaceableIdentifierNode(node, parentNode)) {
+                if (
+                    parentNode
+                    && NodeGuards.isReplaceableIdentifierNode(node, parentNode)
+                    && !NodeMetadata.isRenamedIdentifier(node)
+                ) {
                     const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer.replace(node.name, nodeIdentifier);
                     const newIdentifierName: string = newIdentifier.name;
 
                     if (node.name !== newIdentifierName) {
                         node.name = newIdentifierName;
-                        node.obfuscatedNode = true;
+                        NodeMetadata.set(node, { renamedIdentifier: true });
                     } else {
                         const storedReplaceableIdentifiers: ESTree.Identifier[] = storedReplaceableIdentifiersNamesMap.get(node.name) || [];
 

+ 2 - 2
src/node-transformers/obfuscating-transformers/obfuscating-replacers/identifier-obfuscating-replacers/BaseIdentifierObfuscatingReplacer.ts

@@ -10,7 +10,7 @@ import { IIdentifierObfuscatingReplacer } from '../../../../interfaces/node-tran
 import { IOptions } from '../../../../interfaces/options/IOptions';
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
-import { Nodes } from '../../../../node/Nodes';
+import { NodeFactory } from '../../../../node/NodeFactory';
 
 @injectable()
 export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplacer implements IIdentifierObfuscatingReplacer {
@@ -50,7 +50,7 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
             nodeValue = <string>this.namesMap.get(mapKey);
         }
 
-        return Nodes.getIdentifierNode(nodeValue);
+        return NodeFactory.identifierNode(nodeValue);
     }
 
     /**

+ 4 - 4
src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/BooleanLiteralObfuscatingReplacer.ts

@@ -6,7 +6,7 @@ import * as ESTree from 'estree';
 import { IOptions } from '../../../../interfaces/options/IOptions';
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
-import { Nodes } from '../../../../node/Nodes';
+import { NodeFactory } from '../../../../node/NodeFactory';
 
 @injectable()
 export class BooleanLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer {
@@ -23,7 +23,7 @@ export class BooleanLiteralObfuscatingReplacer extends AbstractObfuscatingReplac
      * @return {ESTree.UnaryExpression}
      */
     private static getTrueUnaryExpressionNode (): ESTree.UnaryExpression {
-        return Nodes.getUnaryExpressionNode(
+        return NodeFactory.unaryExpressionNode(
             '!',
             BooleanLiteralObfuscatingReplacer.getFalseUnaryExpressionNode()
         );
@@ -33,9 +33,9 @@ export class BooleanLiteralObfuscatingReplacer extends AbstractObfuscatingReplac
      * @return {ESTree.UnaryExpression}
      */
     private static getFalseUnaryExpressionNode (): ESTree.UnaryExpression {
-        return Nodes.getUnaryExpressionNode(
+        return NodeFactory.unaryExpressionNode(
             '!',
-            Nodes.getArrayExpressionNode()
+            NodeFactory.arrayExpressionNode()
         );
     }
 

+ 2 - 2
src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/NumberLiteralObfuscatingReplacer.ts

@@ -6,7 +6,7 @@ import * as ESTree from 'estree';
 import { IOptions } from '../../../../interfaces/options/IOptions';
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
-import { Nodes } from '../../../../node/Nodes';
+import { NodeFactory } from '../../../../node/NodeFactory';
 import { Utils } from '../../../../utils/Utils';
 
 @injectable()
@@ -44,6 +44,6 @@ export class NumberLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
             this.numberLiteralCache.set(nodeValue, rawValue);
         }
 
-        return Nodes.getLiteralNode(nodeValue, rawValue);
+        return NodeFactory.literalNode(nodeValue, rawValue);
     }
 }

+ 16 - 14
src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.ts

@@ -3,18 +3,20 @@ import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
+import { TStringArrayStorage } from '../../../../types/storages/TStringArrayStorage';
+
 import { ICryptUtils } from '../../../../interfaces/utils/ICryptUtils';
 import { IEncodedValue } from '../../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/IEncodedValue';
 import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../../interfaces/storages/IStorage';
 import { IStringArrayIndexData } from '../../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/IStringArrayIndexData';
 
 import { StringArrayEncoding } from '../../../../enums/StringArrayEncoding';
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
-import { Nodes } from '../../../../node/Nodes';
+import { NodeMetadata } from '../../../../node/NodeMetadata';
+import { NodeFactory } from '../../../../node/NodeFactory';
 import { Utils } from '../../../../utils/Utils';
 
 @injectable()
@@ -65,19 +67,19 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
     private readonly stringLiteralHexadecimalIndexCache: Map <string, string> = new Map();
 
     /**
-     * @type {IStorage<string>}
+     * @type {TStringArrayStorage}
      */
-    private readonly stringArrayStorage: IStorage<string>;
+    private readonly stringArrayStorage: TStringArrayStorage;
 
     /**
-     * @param {IStorage<string>} stringArrayStorage
+     * @param {TStringArrayStorage} stringArrayStorage
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IRandomGenerator} randomGenerator
      * @param {ICryptUtils} cryptUtils
      * @param {IOptions} options
      */
     constructor (
-        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStorage<string>,
+        @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils,
@@ -106,9 +108,9 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      * @returns {Literal}
      */
     private static getHexadecimalLiteralNode (hexadecimalIndex: string): ESTree.Literal {
-        const hexadecimalLiteralNode: ESTree.Literal = Nodes.getLiteralNode(hexadecimalIndex);
+        const hexadecimalLiteralNode: ESTree.Literal = NodeFactory.literalNode(hexadecimalIndex);
 
-        hexadecimalLiteralNode.obfuscatedNode = true;
+        NodeMetadata.set(hexadecimalLiteralNode, { replacedLiteral: true });
 
         return hexadecimalLiteralNode;
     }
@@ -118,9 +120,9 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      * @returns {Literal}
      */
     private static getRc4KeyLiteralNode (literalValue: string): ESTree.Literal {
-        const rc4KeyLiteralNode: ESTree.Literal = Nodes.getLiteralNode(literalValue);
+        const rc4KeyLiteralNode: ESTree.Literal = NodeFactory.literalNode(literalValue);
 
-        rc4KeyLiteralNode.obfuscatedNode = true;
+        NodeMetadata.set(rc4KeyLiteralNode, { replacedLiteral: true });
 
         return rc4KeyLiteralNode;
     }
@@ -215,7 +217,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      * @returns {Node}
      */
     private replaceWithLiteralNode (value: string): ESTree.Node {
-        return Nodes.getLiteralNode(
+        return NodeFactory.literalNode(
             this.escapeSequenceEncoder.encode(value, this.options.unicodeEscapeSequence)
         );
     }
@@ -250,12 +252,12 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
             ));
         }
 
-        const stringArrayIdentifierNode: ESTree.Identifier = Nodes.getIdentifierNode(stringArrayStorageCallsWrapperName);
+        const stringArrayIdentifierNode: ESTree.Identifier = NodeFactory.identifierNode(stringArrayStorageCallsWrapperName);
 
         // prevent obfuscation of this identifier
-        stringArrayIdentifierNode.obfuscatedNode = true;
+        NodeMetadata.set(stringArrayIdentifierNode, { renamedIdentifier: true });
 
-        return Nodes.getCallExpressionNode(
+        return NodeFactory.callExpressionNode(
             stringArrayIdentifierNode,
             callExpressionArgs
         );

+ 6 - 5
src/node-transformers/preparing-transformers/CustomNodesTransformer.ts

@@ -3,13 +3,14 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
+import { TCustomNodeGroupStorage } from '../../types/storages/TCustomNodeGroupStorage';
+
 import { ICustomNodeGroup } from '../../interfaces/custom-nodes/ICustomNodeGroup';
 import { IObfuscationEventEmitter } from '../../interfaces/event-emitters/IObfuscationEventEmitter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IStackTraceAnalyzer } from '../../interfaces/analyzers/stack-trace-analyzer/IStackTraceAnalyzer';
 import { IStackTraceData } from '../../interfaces/analyzers/stack-trace-analyzer/IStackTraceData';
-import { IStorage } from '../../interfaces/storages/IStorage';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { ObfuscationEvent } from '../../enums/event-emitters/ObfuscationEvent';
@@ -24,9 +25,9 @@ import { NodeGuards } from '../../node/NodeGuards';
 @injectable()
 export class CustomNodesTransformer extends AbstractNodeTransformer {
     /**
-     * @type {IStorage<ICustomNodeGroup>}
+     * @type {TCustomNodeGroupStorage}
      */
-    private readonly customNodeGroupStorage: IStorage<ICustomNodeGroup>;
+    private readonly customNodeGroupStorage: TCustomNodeGroupStorage;
 
     /**
      * @type {IObfuscationEventEmitter}
@@ -46,14 +47,14 @@ export class CustomNodesTransformer extends AbstractNodeTransformer {
     /**
      * @param {IStackTraceAnalyzer} stackTraceAnalyzer
      * @param {IObfuscationEventEmitter} obfuscationEventEmitter
-     * @param {IStorage<ICustomNodeGroup>} customNodeGroupStorage
+     * @param {TCustomNodeGroupStorage} customNodeGroupStorage
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     constructor (
         @inject(ServiceIdentifiers.IStackTraceAnalyzer) stackTraceAnalyzer: IStackTraceAnalyzer,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
-        @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: IStorage<ICustomNodeGroup>,
+        @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: TCustomNodeGroupStorage,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {

+ 7 - 9
src/node-transformers/preparing-transformers/EvaCallExpressionTransformer.ts

@@ -4,8 +4,6 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 import jsStringEscape from 'js-string-escape';
 
-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';
@@ -13,8 +11,8 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -133,7 +131,7 @@ export class EvalCallExpressionTransformer extends AbstractNodeTransformer {
             return callExpressionNode;
         }
 
-        let ast: TStatement[];
+        let ast: ESTree.Statement[];
 
         // wrapping into try-catch to prevent parsing of incorrect `eval` string
         try {
@@ -146,8 +144,8 @@ export class EvalCallExpressionTransformer extends AbstractNodeTransformer {
          * we should wrap AST-tree into the parent function expression node (ast root host node).
          * This function expression node will help to correctly transform AST-tree.
          */
-        const evalRootAstHostNode: ESTree.FunctionExpression = Nodes
-            .getFunctionExpressionNode([], Nodes.getBlockStatementNode(<any>ast));
+        const evalRootAstHostNode: ESTree.FunctionExpression = NodeFactory
+            .functionExpressionNode([], NodeFactory.blockStatementNode(ast));
 
         /**
          * we should store that host node and then extract AST-tree on the `finalizing` stage
@@ -166,10 +164,10 @@ export class EvalCallExpressionTransformer extends AbstractNodeTransformer {
         const targetAst: ESTree.Statement[] = evalRootAstHostNode.body.body;
         const obfuscatedCode: string = NodeUtils.convertStructureToCode(targetAst);
 
-        return Nodes.getCallExpressionNode(
-            Nodes.getIdentifierNode('eval'),
+        return NodeFactory.callExpressionNode(
+            NodeFactory.identifierNode('eval'),
             [
-                Nodes.getLiteralNode(jsStringEscape(obfuscatedCode))
+                NodeFactory.literalNode(jsStringEscape(obfuscatedCode))
             ]
         );
     }

+ 68 - 0
src/node-transformers/preparing-transformers/MetadataTransformer.ts

@@ -0,0 +1,68 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
+
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
+import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeGuards } from '../../node/NodeGuards';
+import { NodeMetadata } from '../../node/NodeMetadata';
+
+/**
+ * Adds metadata properties to each node
+ */
+@injectable()
+export class MetadataTransformer extends AbstractNodeTransformer {
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(randomGenerator, options);
+    }
+
+    /**
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
+     */
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Preparing:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        return this.transformNode(node, parentNode);
+                    }
+                };
+
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * @param {Node} node
+     * @param {Node} parentNode
+     * @returns {Node}
+     */
+    public transformNode (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node {
+        NodeMetadata.set(node, { ignoredNode: false });
+
+        if (NodeGuards.isIdentifierNode(node)) {
+            NodeMetadata.set(node, { renamedIdentifier: false });
+        }
+
+        if (NodeGuards.isLiteralNode(node)) {
+            NodeMetadata.set(node, { replacedLiteral: false });
+        }
+
+        return node;
+    }
+}

+ 4 - 1
src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts

@@ -14,6 +14,7 @@ import { ObfuscatingGuard } from '../../enums/node-transformers/preparing-transf
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { NodeMetadata } from '../../node/NodeMetadata';
 
 /**
  * Adds `ignoredNode` properties to each node
@@ -75,7 +76,9 @@ export class ObfuscatingGuardsTransformer extends AbstractNodeTransformer {
         const obfuscationAllowed: boolean = this.obfuscatingGuards
             .every((nodeGuard: IObfuscatingGuard) => nodeGuard.check(node));
 
-        node.ignoredNode = !obfuscationAllowed;
+        NodeMetadata.set(node, {
+            ignoredNode: !obfuscationAllowed
+        });
 
         return node;
     }

+ 77 - 74
src/node/Nodes.ts → src/node/NodeFactory.ts

@@ -1,3 +1,5 @@
+/* tslint:disable:max-file-line-count */
+
 import * as escodegen from 'escodegen-wallaby';
 import * as ESTree from 'estree';
 
@@ -5,17 +7,17 @@ import { TStatement } from '../types/node/TStatement';
 
 import { NodeType } from '../enums/node/NodeType';
 
-export class Nodes {
+export class NodeFactory {
     /**
      * @param {TStatement[]} body
      * @returns {Program}
      */
-    public static getProgramNode (body: TStatement[] = []): ESTree.Program {
+    public static programNode (body: TStatement[] = []): ESTree.Program {
         return {
             type: NodeType.Program,
             body,
             sourceType: 'script',
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -23,12 +25,13 @@ export class Nodes {
      * @param {(Expression | SpreadElement)[]} elements
      * @returns {ArrayExpression}
      */
-    public static getArrayExpressionNode (
+    public static arrayExpressionNode (
         elements: (ESTree.Expression | ESTree.SpreadElement)[] = []
     ): ESTree.ArrayExpression {
         return {
             type: NodeType.ArrayExpression,
-            elements
+            elements,
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -38,7 +41,7 @@ export class Nodes {
      * @param {Expression} right
      * @returns {AssignmentExpression}
      */
-    public static getAssignmentExpressionNode (
+    public static assignmentExpressionNode (
         operator: ESTree.AssignmentOperator,
         left: ESTree.Pattern | ESTree.MemberExpression,
         right: ESTree.Expression
@@ -48,7 +51,7 @@ export class Nodes {
             operator,
             left,
             right,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -58,7 +61,7 @@ export class Nodes {
      * @param {Expression} right
      * @returns {BinaryExpression}
      */
-    public static getBinaryExpressionNode (
+    public static binaryExpressionNode (
         operator: ESTree.BinaryOperator,
         left: ESTree.Expression,
         right: ESTree.Expression,
@@ -68,7 +71,7 @@ export class Nodes {
             operator,
             left,
             right,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -76,11 +79,11 @@ export class Nodes {
      * @param {Statement[]} body
      * @returns {BlockStatement}
      */
-    public static getBlockStatementNode (body: ESTree.Statement[] = []): ESTree.BlockStatement {
+    public static blockStatementNode (body: ESTree.Statement[] = []): ESTree.BlockStatement {
         return {
             type: NodeType.BlockStatement,
             body,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -88,10 +91,10 @@ export class Nodes {
      * @param {Identifier} label
      * @returns {BreakStatement}
      */
-    public static getBreakStatement (label?: ESTree.Identifier): ESTree.BreakStatement {
+    public static breakStatement (label?: ESTree.Identifier): ESTree.BreakStatement {
         const breakStatementNode: ESTree.BreakStatement = {
             type: NodeType.BreakStatement,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
 
         if (label) {
@@ -106,7 +109,7 @@ export class Nodes {
      * @param {(Expression | SpreadElement)[]} args
      * @returns {CallExpression}
      */
-    public static getCallExpressionNode (
+    public static callExpressionNode (
         callee: ESTree.Expression,
         args: (ESTree.Expression | ESTree.SpreadElement)[] = []
     ): ESTree.CallExpression {
@@ -114,7 +117,7 @@ export class Nodes {
             type: NodeType.CallExpression,
             callee,
             arguments: args,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -122,10 +125,10 @@ export class Nodes {
      * @param {Identifier} label
      * @returns {ContinueStatement}
      */
-    public static getContinueStatement (label?: ESTree.Identifier): ESTree.ContinueStatement {
+    public static continueStatement (label?: ESTree.Identifier): ESTree.ContinueStatement {
         const continueStatementNode: ESTree.ContinueStatement = {
             type: NodeType.ContinueStatement,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
 
         if (label) {
@@ -139,11 +142,11 @@ export class Nodes {
      * @param {Expression} expression
      * @returns {ExpressionStatement}
      */
-    public static getExpressionStatementNode (expression: ESTree.Expression): ESTree.ExpressionStatement {
+    public static expressionStatementNode (expression: ESTree.Expression): ESTree.ExpressionStatement {
         return {
             type: NodeType.ExpressionStatement,
             expression,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -153,18 +156,18 @@ export class Nodes {
      * @param {BlockStatement} body
      * @returns {FunctionDeclaration}
      */
-    public static getFunctionDeclarationNode (
+    public static functionDeclarationNode (
         functionName: string,
         params: ESTree.Identifier[],
         body: ESTree.BlockStatement
     ): ESTree.FunctionDeclaration {
         return {
             type: NodeType.FunctionDeclaration,
-            id: Nodes.getIdentifierNode(functionName),
+            id: NodeFactory.identifierNode(functionName),
             params,
             body,
             generator: false,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -173,7 +176,7 @@ export class Nodes {
      * @param {BlockStatement} body
      * @returns {FunctionExpression}
      */
-    public static getFunctionExpressionNode (
+    public static functionExpressionNode (
         params: ESTree.Identifier[],
         body: ESTree.BlockStatement
     ): ESTree.FunctionExpression {
@@ -182,7 +185,7 @@ export class Nodes {
             params,
             body,
             generator: false,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -192,7 +195,7 @@ export class Nodes {
      * @param {BlockStatement} alternate
      * @returns {IfStatement}
      */
-    public static getIfStatementNode (
+    public static ifStatementNode (
         test: ESTree.Expression,
         consequent: ESTree.BlockStatement,
         alternate?: ESTree.BlockStatement
@@ -202,7 +205,7 @@ export class Nodes {
             test,
             consequent,
             ...alternate && { alternate },
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -210,11 +213,11 @@ export class Nodes {
      * @param {string} name
      * @returns {Identifier}
      */
-    public static getIdentifierNode (name: string): ESTree.Identifier {
+    public static identifierNode (name: string): ESTree.Identifier {
         return {
             type: NodeType.Identifier,
             name,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -223,7 +226,7 @@ export class Nodes {
      * @param {string} raw
      * @returns {Literal}
      */
-    public static getLiteralNode (value: boolean | number | string, raw?: string): ESTree.Literal {
+    public static literalNode (value: boolean | number | string, raw?: string): ESTree.Literal {
         raw = raw !== undefined ? raw : `'${value}'`;
 
         return {
@@ -234,7 +237,7 @@ export class Nodes {
                 content: raw,
                 precedence: escodegen.Precedence.Primary
             },
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -244,7 +247,7 @@ export class Nodes {
      * @param {Expression} right
      * @returns {LogicalExpression}
      */
-    public static getLogicalExpressionNode (
+    public static logicalExpressionNode (
         operator: ESTree.LogicalOperator,
         left: ESTree.Expression,
         right: ESTree.Expression,
@@ -254,7 +257,7 @@ export class Nodes {
             operator,
             left,
             right,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -264,7 +267,7 @@ export class Nodes {
      * @param {boolean} computed
      * @returns {MemberExpression}
      */
-    public static getMemberExpressionNode (
+    public static memberExpressionNode (
         object: ESTree.Expression | ESTree.Super,
         property: ESTree.Expression,
         computed: boolean = false
@@ -274,7 +277,7 @@ export class Nodes {
             computed,
             object,
             property,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -285,7 +288,7 @@ export class Nodes {
      * @param {boolean} computed
      * @returns {MethodDefinition}
      */
-    public static getMethodDefinitionNode (
+    public static methodDefinitionNode (
         key: ESTree.Expression,
         value: ESTree.FunctionExpression,
         kind: 'constructor' | 'method' | 'get' | 'set',
@@ -298,7 +301,7 @@ export class Nodes {
             kind,
             computed,
             static: false,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -306,11 +309,11 @@ export class Nodes {
      * @param {Property[]} properties
      * @returns {ObjectExpression}
      */
-    public static getObjectExpressionNode (properties: ESTree.Property[]): ESTree.ObjectExpression {
+    public static objectExpressionNode (properties: ESTree.Property[]): ESTree.ObjectExpression {
         return {
             type: NodeType.ObjectExpression,
             properties,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -320,7 +323,7 @@ export class Nodes {
      * @param {boolean} computed
      * @returns {Property}
      */
-    public static getPropertyNode (
+    public static propertyNode (
         key: ESTree.Expression,
         value: ESTree.Expression | ESTree.Pattern,
         computed: boolean = false
@@ -333,27 +336,7 @@ export class Nodes {
             method: false,
             shorthand: false,
             computed,
-            obfuscatedNode: false
-        };
-    }
-
-    /**
-     * @param {UnaryOperator} operator
-     * @param {Expression} argument
-     * @param {true} prefix
-     * @returns {UnaryExpression}
-     */
-    public static getUnaryExpressionNode (
-        operator: ESTree.UnaryOperator,
-        argument: ESTree.Expression,
-        prefix: true = true
-    ): ESTree.UnaryExpression {
-        return {
-            type: NodeType.UnaryExpression,
-            operator,
-            argument,
-            prefix,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -361,11 +344,11 @@ export class Nodes {
      * @param {Expression} argument
      * @returns {ReturnStatement}
      */
-    public static getReturnStatementNode (argument: ESTree.Expression): ESTree.ReturnStatement {
+    public static returnStatementNode (argument: ESTree.Expression): ESTree.ReturnStatement {
         return {
             type: NodeType.ReturnStatement,
             argument,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -374,7 +357,7 @@ export class Nodes {
      * @param {SwitchCase[]} cases
      * @returns {SwitchStatement}
      */
-    public static getSwitchStatementNode (
+    public static switchStatementNode (
         discriminant: ESTree.Expression,
         cases: ESTree.SwitchCase[]
     ): ESTree.SwitchStatement {
@@ -382,7 +365,7 @@ export class Nodes {
             type: NodeType.SwitchStatement,
             discriminant,
             cases,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -391,12 +374,32 @@ export class Nodes {
      * @param {Statement[]} consequent
      * @returns {SwitchCase}
      */
-    public static getSwitchCaseNode (test: ESTree.Expression, consequent: ESTree.Statement[]): ESTree.SwitchCase {
+    public static switchCaseNode (test: ESTree.Expression, consequent: ESTree.Statement[]): ESTree.SwitchCase {
         return {
             type: NodeType.SwitchCase,
             test,
             consequent,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
+        };
+    }
+
+    /**
+     * @param {UnaryOperator} operator
+     * @param {Expression} argument
+     * @param {true} prefix
+     * @returns {UnaryExpression}
+     */
+    public static unaryExpressionNode (
+        operator: ESTree.UnaryOperator,
+        argument: ESTree.Expression,
+        prefix: true = true
+    ): ESTree.UnaryExpression {
+        return {
+            type: NodeType.UnaryExpression,
+            operator,
+            argument,
+            prefix,
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -405,13 +408,13 @@ export class Nodes {
      * @param {Expression} argumentExpr
      * @returns {UpdateExpression}
      */
-    public static getUpdateExpressionNode (operator: ESTree.UpdateOperator, argumentExpr: ESTree.Expression): ESTree.UpdateExpression {
+    public static updateExpressionNode (operator: ESTree.UpdateOperator, argumentExpr: ESTree.Expression): ESTree.UpdateExpression {
         return {
             type: NodeType.UpdateExpression,
             operator,
             argument: argumentExpr,
             prefix: false,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -420,7 +423,7 @@ export class Nodes {
      * @param {string} kind
      * @returns {VariableDeclaration}
      */
-    public static getVariableDeclarationNode (
+    public static variableDeclarationNode (
         declarations: ESTree.VariableDeclarator[] = [],
         kind: 'var' | 'let' | 'const' = 'var'
     ): ESTree.VariableDeclaration {
@@ -428,7 +431,7 @@ export class Nodes {
             type: NodeType.VariableDeclaration,
             declarations,
             kind,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -437,12 +440,12 @@ export class Nodes {
      * @param {Expression | null} init
      * @returns {VariableDeclarator}
      */
-    public static getVariableDeclaratorNode (id: ESTree.Identifier, init: ESTree.Expression | null): ESTree.VariableDeclarator {
+    public static variableDeclaratorNode (id: ESTree.Identifier, init: ESTree.Expression | null): ESTree.VariableDeclarator {
         return {
             type: NodeType.VariableDeclarator,
             id,
             init,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 
@@ -451,12 +454,12 @@ export class Nodes {
      * @param {Statement} body
      * @returns {WhileStatement}
      */
-    public static getWhileStatementNode (test: ESTree.Expression, body: ESTree.Statement): ESTree.WhileStatement {
+    public static whileStatementNode (test: ESTree.Expression, body: ESTree.Statement): ESTree.WhileStatement {
         return {
             type: NodeType.WhileStatement,
             test,
             body,
-            obfuscatedNode: false
+            metadata: { ignoredNode: false }
         };
     }
 }

+ 46 - 0
src/node/NodeMetadata.ts

@@ -0,0 +1,46 @@
+import * as ESTree from 'estree';
+
+export class NodeMetadata {
+    /**
+     * @param {T} node
+     * @param {Partial<T["metadata"]>} metadata
+     */
+    public static set <T extends ESTree.Node = ESTree.Node> (node: T, metadata: Partial<T['metadata']>): void {
+        node.metadata = Object.assign(node.metadata || {}, metadata);
+    }
+
+    /**
+     * @param {Node} node
+     * @param {keyof T} metadataKey
+     * @returns {T[keyof T] | undefined}
+     */
+    public static get <T extends ESTree.BaseNodeMetadata> (node: ESTree.Node, metadataKey: keyof T): T[keyof T] | undefined {
+        return node.metadata !== undefined
+            ? (<T>node.metadata)[metadataKey]
+            : undefined;
+    }
+
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    public static isIgnoredNode (node: ESTree.Node): boolean {
+        return NodeMetadata.get(node, 'ignoredNode') === true;
+    }
+
+    /**
+     * @param {Node} identifierNode
+     * @returns {boolean}
+     */
+    public static isRenamedIdentifier (identifierNode: ESTree.Identifier): boolean {
+        return NodeMetadata.get<ESTree.IdentifierNodeMetadata>(identifierNode, 'renamedIdentifier') === true;
+    }
+
+    /**
+     * @param {Node} literalNode
+     * @returns {boolean}
+     */
+    public static isReplacedLiteral (literalNode: ESTree.Literal): boolean {
+        return NodeMetadata.get<ESTree.LiteralNodeMetadata>(literalNode, 'replacedLiteral') === true;
+    }
+}

+ 14 - 6
src/node/NodeUtils.ts

@@ -9,6 +9,7 @@ import { TObject } from '../types/TObject';
 import { TStatement } from '../types/node/TStatement';
 
 import { NodeGuards } from './NodeGuards';
+import { NodeMetadata } from './NodeMetadata';
 
 export class NodeUtils {
     /**
@@ -40,15 +41,23 @@ export class NodeUtils {
 
     /**
      * @param {string} code
-     * @returns {TStatement[]}
+     * @returns {Statement[]}
      */
-    public static convertCodeToStructure (code: string): TStatement[] {
+    public static convertCodeToStructure (code: string): ESTree.Statement[] {
         let structure: ESTree.Program = esprima.parseScript(code);
 
         structure = NodeUtils.addXVerbatimPropertyToLiterals(structure);
         structure = NodeUtils.parentize(structure);
 
-        return structure.body;
+        estraverse.replace(structure, {
+            enter: (node: ESTree.Node): ESTree.Node => {
+                NodeMetadata.set(node, { ignoredNode: false });
+
+                return node;
+            }
+        });
+
+        return <ESTree.Statement[]>structure.body;
     }
 
     /**
@@ -136,7 +145,6 @@ export class NodeUtils {
      */
     public static parentizeNode <T extends ESTree.Node = ESTree.Node> (node: T, parentNode: ESTree.Node | null): T {
         node.parentNode = parentNode || node;
-        node.obfuscatedNode = false;
 
         return node;
     }
@@ -157,9 +165,9 @@ export class NodeUtils {
                 continue;
             }
 
-            const value: any = node[property];
+            const value: T[keyof T] = node[property];
 
-            let clonedValue: any | null;
+            let clonedValue: T[keyof T] | T[keyof T][] | null;
 
             if (value === null || value instanceof RegExp) {
                 clonedValue = value;

+ 1 - 1
src/options/Options.ts

@@ -211,7 +211,7 @@ export class Options implements IOptions {
     /**
      * @type {ObfuscationTarget}
      */
-    @IsIn([ObfuscationTarget.Browser, ObfuscationTarget.Extension, ObfuscationTarget.Node])
+    @IsIn([ObfuscationTarget.Browser, ObfuscationTarget.BrowserNoEval, ObfuscationTarget.Node])
     public readonly target!: ObfuscationTarget;
 
     /**

+ 13 - 13
src/storages/ArrayStorage.ts

@@ -1,14 +1,14 @@
 import { inject, injectable, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
+import { IArrayStorage } from '../interfaces/storages/IArrayStorage';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../interfaces/storages/IStorage';
 
 import { initializable } from '../decorators/Initializable';
 
 @injectable()
-export abstract class ArrayStorage <T> implements IStorage <T> {
+export abstract class ArrayStorage <V> implements IArrayStorage <V> {
     /**
      * @type {IRandomGenerator}
      */
@@ -20,10 +20,10 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
     protected readonly options: IOptions;
 
     /**
-     * @type {T[]}
+     * @type {V[]}
      */
     @initializable()
-    protected storage!: T[];
+    protected storage!: V[];
 
     /**
      * @type {string}
@@ -56,10 +56,10 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
 
     /**
      * @param {number} key
-     * @returns {T}
+     * @returns {V}
      */
-    public get (key: number): T {
-        const value: T | undefined = this.storage[key];
+    public get (key: number): V {
+        const value: V | undefined = this.storage[key];
 
         if (!value) {
             throw new Error(`No value found in array storage with key \`${key}\``);
@@ -69,10 +69,10 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
     }
 
     /**
-     * @param {T} value
+     * @param {V} value
      * @returns {number}
      */
-    public getKeyOf (value: T): number | null {
+    public getKeyOf (value: V): number | null {
         const key: number = this.storage.indexOf(value);
 
         return key >= 0 ? key : null;
@@ -86,9 +86,9 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
     }
 
     /**
-     * @returns {T[]}
+     * @returns {V[]}
      */
-    public getStorage (): T[] {
+    public getStorage (): V[] {
         return this.storage;
     }
 
@@ -113,9 +113,9 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
 
     /**
      * @param {number} key
-     * @param {T} value
+     * @param {V} value
      */
-    public set (key: number, value: T): void {
+    public set (key: number, value: V): void {
         if (key === this.storageLength) {
             this.storage.push(value);
         } else {

+ 18 - 18
src/storages/MapStorage.ts

@@ -1,14 +1,14 @@
 import { inject, injectable, postConstruct } from 'inversify';
 import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
+import { IMapStorage } from '../interfaces/storages/IMapStorage';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
-import { IStorage } from '../interfaces/storages/IStorage';
 
 import { initializable } from '../decorators/Initializable';
 
 @injectable()
-export abstract class MapStorage <T> implements IStorage <T> {
+export abstract class MapStorage <K, V> implements IMapStorage <K, V> {
     /**
      * @type {IOptions}
      */
@@ -26,10 +26,10 @@ export abstract class MapStorage <T> implements IStorage <T> {
     protected storageId!: string;
 
     /**
-     * @type {Map <string | number, T>}
+     * @type {Map <K, V>}
      */
     @initializable()
-    protected storage!: Map <string | number, T>;
+    protected storage!: Map <K, V>;
 
     /**
      * @param {IRandomGenerator} randomGenerator
@@ -45,16 +45,16 @@ export abstract class MapStorage <T> implements IStorage <T> {
 
     @postConstruct()
     public initialize (): void {
-        this.storage = new Map <string | number, T>();
+        this.storage = new Map <K, V>();
         this.storageId = this.randomGenerator.getRandomString(6);
     }
 
     /**
-     * @param {string | number} key
-     * @returns {T}
+     * @param {K} key
+     * @returns {V}
      */
-    public get (key: string | number): T {
-        const value: T | undefined = this.storage.get(key);
+    public get (key: K): V {
+        const value: V | undefined = this.storage.get(key);
 
         if (!value) {
             throw new Error(`No value found in map storage with key \`${key}\``);
@@ -64,10 +64,10 @@ export abstract class MapStorage <T> implements IStorage <T> {
     }
 
     /**
-     * @param {T} value
-     * @returns {string | number | null}
+     * @param {V} value
+     * @returns {K | null}
      */
-    public getKeyOf (value: T): string | number | null {
+    public getKeyOf (value: V): K | null {
         for (const [key, storageValue] of this.storage) {
             if (value === storageValue) {
                 return key;
@@ -85,9 +85,9 @@ export abstract class MapStorage <T> implements IStorage <T> {
     }
 
     /**
-     * @returns {Map <string | number, T>}
+     * @returns {Map<K, V>}
      */
-    public getStorage (): Map <string | number, T> {
+    public getStorage (): Map <K, V> {
         return this.storage;
     }
 
@@ -103,7 +103,7 @@ export abstract class MapStorage <T> implements IStorage <T> {
      * @param {boolean} mergeId
      */
     public mergeWith (storage: this, mergeId: boolean = false): void {
-        this.storage = new Map <string | number, T>([...this.storage, ...storage.getStorage()]);
+        this.storage = new Map <K, V>([...this.storage, ...storage.getStorage()]);
 
         if (mergeId) {
             this.storageId = storage.getStorageId();
@@ -111,10 +111,10 @@ export abstract class MapStorage <T> implements IStorage <T> {
     }
 
     /**
-     * @param {string | number} key
-     * @param {T} value
+     * @param {K} key
+     * @param {V} value
      */
-    public set (key: string | number, value: T): void {
+    public set (key: K, value: V): void {
         this.storage.set(key, value);
     }
 }

+ 1 - 1
src/storages/control-flow/ControlFlowStorage.ts

@@ -8,7 +8,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { MapStorage } from '../MapStorage';
 
 @injectable()
-export class ControlFlowStorage extends MapStorage <ICustomNode> {
+export class ControlFlowStorage extends MapStorage <string, ICustomNode> {
     /**
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options

+ 1 - 1
src/storages/custom-node-group/CustomNodeGroupStorage.ts

@@ -12,7 +12,7 @@ import { CustomNodeGroup } from '../../enums/custom-nodes/CustomNodeGroup';
 import { MapStorage } from '../MapStorage';
 
 @injectable()
-export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
+export class CustomNodeGroupStorage extends MapStorage <string, ICustomNodeGroup> {
     /**
      * @type {CustomNodeGroup[]}
      */

+ 0 - 5
src/types/container/TInversifyContainerModuleFactory.d.ts

@@ -1,5 +0,0 @@
-import { interfaces } from 'inversify';
-
-import { TInputOptions } from '../options/TInputOptions';
-
-export type TInversifyContainerModuleFactory = (options: TInputOptions) => interfaces.ContainerModule;

+ 2 - 3
src/types/container/node-transformers/TControlFlowStorageFactory.d.ts

@@ -1,4 +1,3 @@
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { IStorage } from '../../../interfaces/storages/IStorage';
+import { TControlFlowStorage } from '../../storages/TControlFlowStorage';
 
-export type TControlFlowStorageFactory = () => IStorage<ICustomNode>;
+export type TControlFlowStorageFactory = () => TControlFlowStorage;

+ 0 - 6
src/types/node-transformers/TNodeTransformer.d.ts

@@ -1,6 +0,0 @@
-import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
-import { INodeTransformer } from '../../interfaces/node-transformers/INodeTransformer';
-import { IOptions } from '../../interfaces/options/IOptions';
-import { IStorage } from '../../interfaces/storages/IStorage';
-
-export type TNodeTransformer = (new (customNodesStorage: IStorage<ICustomNode>, options: IOptions) => INodeTransformer);

+ 2 - 2
src/types/storages/TControlFlowStorage.d.ts

@@ -1,4 +1,4 @@
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
-import { IStorage } from '../../interfaces/storages/IStorage';
+import { IMapStorage } from '../../interfaces/storages/IMapStorage';
 
-export type TControlFlowStorage = IStorage<ICustomNode>;
+export type TControlFlowStorage = IMapStorage <string, ICustomNode>;

+ 2 - 2
src/types/storages/TCustomNodeGroupStorage.d.ts

@@ -1,4 +1,4 @@
 import { ICustomNodeGroup } from '../../interfaces/custom-nodes/ICustomNodeGroup';
-import { IStorage } from '../../interfaces/storages/IStorage';
+import { IMapStorage } from '../../interfaces/storages/IMapStorage';
 
-export type TCustomNodeGroupStorage = IStorage<ICustomNodeGroup>;
+export type TCustomNodeGroupStorage = IMapStorage <string, ICustomNodeGroup>;

+ 2 - 2
src/types/storages/TStringArrayStorage.d.ts

@@ -1,3 +1,3 @@
-import { IStorage } from '../../interfaces/storages/IStorage';
+import { IArrayStorage } from '../../interfaces/storages/IArrayStorage';
 
-export type TStringArrayStorage = IStorage<string>;
+export type TStringArrayStorage = IArrayStorage <string>;

+ 1 - 1
src/utils/Utils.ts

@@ -67,7 +67,7 @@ export class Utils {
         return Array
             .from(string)
             .map((character: string): string => {
-                return JSFuck[<any>character] || character;
+                return JSFuck[<keyof typeof JSFuck>character] || character;
             })
             .join(' + ');
     }

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

@@ -16,8 +16,8 @@ import { IStackTraceData } from '../../../../src/interfaces/analyzers/stack-trac
 import { readFileAsString } from '../../../helpers/readFileAsString';
 
 import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade';
+import { NodeFactory } from '../../../../src/node/NodeFactory';
 import { NodeGuards } from '../../../../src/node/NodeGuards';
-import { Nodes } from '../../../../src/node/Nodes';
 import { NodeUtils } from '../../../../src/node/NodeUtils';
 
 /**
@@ -165,7 +165,7 @@ describe('StackTraceAnalyzer', () => {
         describe('Variant #1: basic-1', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/basic-1.js');
-                const astTree: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     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: TNodeWithBlockScope = Nodes.getProgramNode(
+                const astTree: TNodeWithBlockScope = NodeFactory.programNode(
                     NodeUtils.convertCodeToStructure(code)
                 );
 

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

@@ -11,7 +11,7 @@ import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscator
 describe('BinaryExpressionControlFlowReplacer', function () {
     this.timeout(100000);
 
-    describe('replace (binaryExpressionNode: ESTree.BinaryExpression,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
+    describe('replace (binaryExpressionNode, parentNode, controlFlowStorage)', () => {
         describe('Variant #1 - single binary expression', () => {
             const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{5}'\]\(0x1, *0x2\);/;
 

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

@@ -11,7 +11,7 @@ import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscator
 describe('CallExpressionControlFlowReplacer', function () {
     this.timeout(100000);
 
-    describe('replace (callExpressionNode: ESTree.CallExpression,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
+    describe('replace (callExpressionNode, parentNode, controlFlowStorage)', () => {
         describe('Variant #1 - single call expression', () => {
             const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{5}'\]\(_0x([a-f0-9]){4,6}, *0x1, *0x2\);/;
 

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

@@ -11,7 +11,7 @@ import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscator
 describe('LogicalExpressionControlFlowReplacer', function () {
     this.timeout(100000);
 
-    describe('replace (logicalExpressionNode: ESTree.LogicalExpression,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
+    describe('replace (logicalExpressionNode, parentNode, controlFlowStorage)', () => {
         describe('Variant #1 - single logical expression', () => {
             const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{5}'\]\(!!\[\], *!\[\]\);/;
 

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

@@ -9,7 +9,7 @@ import { readFileAsString } from '../../../../../helpers/readFileAsString';
 import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscatorFacade';
 
 describe('StringLiteralControlFlowReplacer', () => {
-    describe('replace (literalNode: ESTree.Literal,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
+    describe('replace (literalNode, parentNode, controlFlowStorage)', () => {
         const controlFlowStorageStringLiteralRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *\{'\w{5}' *: *'test'\};/;
         const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{5}'\];/;
 

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

@@ -115,7 +115,7 @@ describe('DebugProtectionFunctionCallTemplate (): string', () => {
                 {
                     ...NO_ADDITIONAL_NODES_PRESET,
                     debugProtection: true,
-                    target: ObfuscationTarget.Extension
+                    target: ObfuscationTarget.BrowserNoEval
                 }
             );
 

+ 1 - 0
test/index.spec.ts

@@ -22,6 +22,7 @@ import './unit-tests/javascript-obfuscator/JavaScriptObfuscator.spec';
 import './unit-tests/logger/Logger.spec';
 import './unit-tests/node/node-appender/NodeAppender.spec';
 import './unit-tests/node/node-guards/NodeGuards.spec';
+import './unit-tests/node/node-metadata/NodeMetadata.spec';
 import './unit-tests/node/node-utils/NodeUtils.spec';
 import './unit-tests/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.spec';
 import './unit-tests/obfuscation-result/ObfuscationResult.spec';

+ 7 - 6
test/unit-tests/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.spec.ts

@@ -11,8 +11,9 @@ import { IInversifyContainerFacade } from '../../../../src/interfaces/container/
 import { INodeTransformer } from '../../../../src/interfaces/node-transformers/INodeTransformer';
 
 import { NodeTransformer } from '../../../../src/enums/node-transformers/NodeTransformer';
-import { Nodes } from '../../../../src/node/Nodes';
+import { NodeFactory } from '../../../../src/node/NodeFactory';
 import { NodeUtils } from '../../../../src/node/NodeUtils';
+import { NodeMetadata } from '../../../../src/node/NodeMetadata';
 
 describe('ObfuscatingGuardsTransformer', () => {
     describe('transformNode (node: ESTree.Node, parentNode: ESTree.Node): ESTree.Node', () => {
@@ -28,7 +29,7 @@ describe('ObfuscatingGuardsTransformer', () => {
         });
 
         describe('Variant #1: valid node', () => {
-            const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
+            const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
 
             const expectedResult: ESTree.Identifier = NodeUtils.clone(identifier);
 
@@ -37,7 +38,7 @@ describe('ObfuscatingGuardsTransformer', () => {
             before(() => {
                 identifier.parentNode = identifier;
 
-                expectedResult.ignoredNode = false;
+                NodeMetadata.set(expectedResult, { ignoredNode: false });
 
                 result = <ESTree.Identifier>obfuscatingGuardsTransformer.transformNode(identifier, identifier);
             });
@@ -48,8 +49,8 @@ describe('ObfuscatingGuardsTransformer', () => {
         });
 
         describe('Variant #2: invalid node', () => {
-            const expressionStatement: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(
-                Nodes.getIdentifierNode('foo')
+            const expressionStatement: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(
+                NodeFactory.identifierNode('foo')
             );
 
             const expectedResult: ESTree.ExpressionStatement = NodeUtils.clone(expressionStatement);
@@ -63,7 +64,7 @@ describe('ObfuscatingGuardsTransformer', () => {
 
                 expectedResult.directive = 'use strict';
                 expectedResult.parentNode = expectedResult;
-                expectedResult.ignoredNode = true;
+                NodeMetadata.set(expectedResult, { ignoredNode: true });
 
                 result = <ESTree.ExpressionStatement>obfuscatingGuardsTransformer
                     .transformNode(expressionStatement, expressionStatement);

+ 2 - 2
test/unit-tests/node/node-appender/NodeAppender.spec.ts

@@ -16,7 +16,7 @@ import { readFileAsString } from '../../../helpers/readFileAsString';
 
 import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade';
 import { NodeAppender } from '../../../../src/node/NodeAppender';
-import { Nodes } from '../../../../src/node/Nodes';
+import { NodeFactory } from '../../../../src/node/NodeFactory';
 import { NodeUtils } from '../../../../src/node/NodeUtils';
 
 /**
@@ -34,7 +34,7 @@ const convertCodeToStructure: (fixturePath: string) => TStatement[] = (fixturePa
  * @return {ESTree.Program}
  */
 const convertCodeToAst: (fixturePath: string) => ESTree.Program = (fixturePath) => {
-    return Nodes.getProgramNode(convertCodeToStructure(fixturePath));
+    return NodeFactory.programNode(convertCodeToStructure(fixturePath));
 };
 
 describe('NodeAppender', () => {

+ 59 - 59
test/unit-tests/node/node-guards/NodeGuards.spec.ts

@@ -2,8 +2,8 @@ import * as ESTree from 'estree';
 
 import { assert } from 'chai';
 
-import { Nodes } from '../../../../src/node/Nodes';
 import { NodeGuards } from '../../../../src/node/NodeGuards';
+import { NodeFactory } from '../../../../src/node/NodeFactory';
 import { NodeUtils } from '../../../../src/node/NodeUtils';
 
 describe('NodeGuards', () => {
@@ -11,8 +11,8 @@ describe('NodeGuards', () => {
         describe('truthful checks', () => {
             describe('Variant #1: block statement of function declaration', () => {
                 const expectedResult: boolean = true;
-                const node: ESTree.Node = Nodes.getBlockStatementNode();
-                const parentNode: ESTree.FunctionDeclaration = Nodes.getFunctionDeclarationNode(
+                const node: ESTree.Node = NodeFactory.blockStatementNode();
+                const parentNode: ESTree.FunctionDeclaration = NodeFactory.functionDeclarationNode(
                     'foo',
                     [],
                     node
@@ -32,8 +32,8 @@ describe('NodeGuards', () => {
 
             describe('Variant #2: block statement of function expression', () => {
                 const expectedResult: boolean = true;
-                const node: ESTree.Node = Nodes.getBlockStatementNode();
-                const parentNode: ESTree.FunctionExpression = Nodes.getFunctionExpressionNode(
+                const node: ESTree.Node = NodeFactory.blockStatementNode();
+                const parentNode: ESTree.FunctionExpression = NodeFactory.functionExpressionNode(
                     [],
                     node
                 );
@@ -54,20 +54,20 @@ describe('NodeGuards', () => {
         describe('false checks', () => {
             describe('Variant #1: switch-case node', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getSwitchCaseNode(
-                    Nodes.getLiteralNode(1),
+                const node: ESTree.Node = NodeFactory.switchCaseNode(
+                    NodeFactory.literalNode(1),
                     []
                 );
-                const parentNode: ESTree.FunctionDeclaration = Nodes.getFunctionDeclarationNode(
+                const parentNode: ESTree.FunctionDeclaration = NodeFactory.functionDeclarationNode(
                     'foo',
                     [],
-                    Nodes.getBlockStatementNode([
-                        Nodes.getSwitchStatementNode(
-                            Nodes.getMemberExpressionNode(
-                                Nodes.getIdentifierNode('bar'),
-                                Nodes.getUpdateExpressionNode(
+                    NodeFactory.blockStatementNode([
+                        NodeFactory.switchStatementNode(
+                            NodeFactory.memberExpressionNode(
+                                NodeFactory.identifierNode('bar'),
+                                NodeFactory.updateExpressionNode(
                                     '++',
-                                    Nodes.getIdentifierNode('baz')
+                                    NodeFactory.identifierNode('baz')
                                 ),
                                 true
                             ),
@@ -90,14 +90,14 @@ describe('NodeGuards', () => {
 
             describe('Variant #2: literal node', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getLiteralNode(1);
-                const parentNode: ESTree.FunctionDeclaration = Nodes.getFunctionDeclarationNode(
+                const node: ESTree.Node = NodeFactory.literalNode(1);
+                const parentNode: ESTree.FunctionDeclaration = NodeFactory.functionDeclarationNode(
                     'foo',
                     [],
-                    Nodes.getBlockStatementNode([
-                        Nodes.getExpressionStatementNode(
-                            Nodes.getCallExpressionNode(
-                                Nodes.getIdentifierNode('bar'),
+                    NodeFactory.blockStatementNode([
+                        NodeFactory.expressionStatementNode(
+                            NodeFactory.callExpressionNode(
+                                NodeFactory.identifierNode('bar'),
                                 [node]
                             )
                         )
@@ -118,9 +118,9 @@ describe('NodeGuards', () => {
 
             describe('Variant #3: block statement of if statement', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getBlockStatementNode();
-                const parentNode: ESTree.IfStatement = Nodes.getIfStatementNode(
-                    Nodes.getIdentifierNode('foo'),
+                const node: ESTree.Node = NodeFactory.blockStatementNode();
+                const parentNode: ESTree.IfStatement = NodeFactory.ifStatementNode(
+                    NodeFactory.identifierNode('foo'),
                     node
                 );
 
@@ -142,7 +142,7 @@ describe('NodeGuards', () => {
         describe('truthful checks', () => {
             describe('Variant #1: program node', () => {
                 const expectedResult: boolean = true;
-                const node: ESTree.Node = Nodes.getProgramNode();
+                const node: ESTree.Node = NodeFactory.programNode();
 
                 let result: boolean;
 
@@ -157,7 +157,7 @@ describe('NodeGuards', () => {
 
             describe('Variant #2: block statement node', () => {
                 const expectedResult: boolean = true;
-                const node: ESTree.Node = Nodes.getBlockStatementNode();
+                const node: ESTree.Node = NodeFactory.blockStatementNode();
 
                 let result: boolean;
 
@@ -172,8 +172,8 @@ describe('NodeGuards', () => {
 
             describe('Variant #3: switch case node', () => {
                 const expectedResult: boolean = true;
-                const node: ESTree.Node = Nodes.getSwitchCaseNode(
-                    Nodes.getLiteralNode(1),
+                const node: ESTree.Node = NodeFactory.switchCaseNode(
+                    NodeFactory.literalNode(1),
                     []
                 );
 
@@ -192,7 +192,7 @@ describe('NodeGuards', () => {
         describe('false checks', () => {
             describe('Variant #1: literal node', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getLiteralNode(1);
+                const node: ESTree.Node = NodeFactory.literalNode(1);
 
                 let result: boolean;
 
@@ -207,7 +207,7 @@ describe('NodeGuards', () => {
 
             describe('Variant #2: identifier node', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getIdentifierNode('foo');
+                const node: ESTree.Node = NodeFactory.identifierNode('foo');
 
                 let result: boolean;
 
@@ -222,9 +222,9 @@ describe('NodeGuards', () => {
 
             describe('Variant #3: if-statement node', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getIfStatementNode(
-                    Nodes.getIdentifierNode('foo'),
-                    Nodes.getBlockStatementNode()
+                const node: ESTree.Node = NodeFactory.ifStatementNode(
+                    NodeFactory.identifierNode('foo'),
+                    NodeFactory.blockStatementNode()
                 );
 
                 let result: boolean;
@@ -240,8 +240,8 @@ describe('NodeGuards', () => {
 
             describe('Variant #4: switch-statement node', () => {
                 const expectedResult: boolean = false;
-                const node: ESTree.Node = Nodes.getSwitchStatementNode(
-                    Nodes.getIdentifierNode('foo'),
+                const node: ESTree.Node = NodeFactory.switchStatementNode(
+                    NodeFactory.identifierNode('foo'),
                     []
                 );
 
@@ -262,11 +262,11 @@ describe('NodeGuards', () => {
         describe('truthful checks', () => {
             describe('Variant #1: parent node is function declaration node', () => {
                 const expectedResult: boolean = true;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getFunctionDeclarationNode(
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.functionDeclarationNode(
                     'bar',
                     [identifier],
-                    Nodes.getBlockStatementNode()
+                    NodeFactory.blockStatementNode()
                 );
 
                 let result: boolean;
@@ -283,10 +283,10 @@ describe('NodeGuards', () => {
 
             describe('Variant #2: parent node is computed property node', () => {
                 const expectedResult: boolean = true;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getPropertyNode(
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.propertyNode(
                     identifier,
-                    Nodes.getLiteralNode('bar'),
+                    NodeFactory.literalNode('bar'),
                     true
                 );
 
@@ -304,9 +304,9 @@ describe('NodeGuards', () => {
 
             describe('Variant #4: parent node is computed member expression node', () => {
                 const expectedResult: boolean = true;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getMemberExpressionNode(
-                    Nodes.getIdentifierNode('bar'),
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.memberExpressionNode(
+                    NodeFactory.identifierNode('bar'),
                     identifier,
                     true
                 );
@@ -325,10 +325,10 @@ describe('NodeGuards', () => {
 
             describe('Variant #4: parent node is computed method definition node', () => {
                 const expectedResult: boolean = true;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getMethodDefinitionNode(
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.methodDefinitionNode(
                     identifier,
-                    Nodes.getFunctionExpressionNode([], Nodes.getBlockStatementNode()),
+                    NodeFactory.functionExpressionNode([], NodeFactory.blockStatementNode()),
                     'method',
                     true
                 );
@@ -349,10 +349,10 @@ describe('NodeGuards', () => {
         describe('false checks', () => {
             describe('Variant #1: node isn\'t an identifier', () => {
                 const expectedResult: boolean = false;
-                const literal: ESTree.Literal = Nodes.getLiteralNode(1);
-                const parentNode: ESTree.Node = Nodes.getExpressionStatementNode(
-                    Nodes.getCallExpressionNode(
-                        Nodes.getIdentifierNode('foo'),
+                const literal: ESTree.Literal = NodeFactory.literalNode(1);
+                const parentNode: ESTree.Node = NodeFactory.expressionStatementNode(
+                    NodeFactory.callExpressionNode(
+                        NodeFactory.identifierNode('foo'),
                         [literal]
                     )
                 );
@@ -371,10 +371,10 @@ describe('NodeGuards', () => {
 
             describe('Variant #2: parent node isn\'t computed property node', () => {
                 const expectedResult: boolean = false;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getPropertyNode(
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.propertyNode(
                     identifier,
-                    Nodes.getLiteralNode('bar'),
+                    NodeFactory.literalNode('bar'),
                     false
                 );
 
@@ -392,9 +392,9 @@ describe('NodeGuards', () => {
 
             describe('Variant #3: parent node isn\'t computed member expression node', () => {
                 const expectedResult: boolean = false;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getMemberExpressionNode(
-                    Nodes.getIdentifierNode('bar'),
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.memberExpressionNode(
+                    NodeFactory.identifierNode('bar'),
                     identifier,
                     false
                 );
@@ -413,10 +413,10 @@ describe('NodeGuards', () => {
 
             describe('Variant #4: parent node isn\'t computed method definition node', () => {
                 const expectedResult: boolean = false;
-                const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-                const parentNode: ESTree.Node = Nodes.getMethodDefinitionNode(
+                const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+                const parentNode: ESTree.Node = NodeFactory.methodDefinitionNode(
                     identifier,
-                    Nodes.getFunctionExpressionNode([], Nodes.getBlockStatementNode()),
+                    NodeFactory.functionExpressionNode([], NodeFactory.blockStatementNode()),
                     'method',
                     false
                 );

+ 103 - 0
test/unit-tests/node/node-metadata/NodeMetadata.spec.ts

@@ -0,0 +1,103 @@
+import 'reflect-metadata';
+
+import * as ESTree from 'estree';
+
+import { assert } from 'chai';
+
+import { NodeMetadata } from '../../../../src/node/NodeMetadata';
+import { NodeFactory } from '../../../../src/node/NodeFactory';
+
+describe('NodeMetadata', () => {
+    describe('set', () => {
+        const expectedMetadata: ESTree.IdentifierNodeMetadata = {
+            ignoredNode: true,
+            renamedIdentifier: true
+        };
+
+        let node: ESTree.Identifier;
+
+        before(() => {
+            node = NodeFactory.identifierNode('foo');
+            NodeMetadata.set(node, {
+                ignoredNode: true,
+                renamedIdentifier: true
+            })
+        });
+
+        it('should set metadata to the node', () => {
+            assert.deepPropertyVal(node, 'metadata', expectedMetadata);
+        });
+    });
+
+    describe('get', () => {
+        const expectedValue: boolean = true;
+
+        let node: ESTree.Identifier,
+            value: boolean | undefined;
+
+        before(() => {
+            node = NodeFactory.identifierNode('foo');
+            node.metadata = {};
+            node.metadata.renamedIdentifier = true;
+            value = NodeMetadata.get<ESTree.IdentifierNodeMetadata>(node, 'renamedIdentifier');
+        });
+
+        it('should get metadata value of the node', () => {
+            assert.equal(value, expectedValue);
+        });
+    });
+
+    describe('isIgnoredNode (node: ESTree.Node): boolean', () => {
+        const expectedValue: boolean = true;
+
+        let node: ESTree.Identifier,
+            value: boolean | undefined;
+
+        before(() => {
+            node = NodeFactory.identifierNode('foo');
+            node.metadata = {};
+            node.metadata.ignoredNode = true;
+            value = NodeMetadata.isIgnoredNode(node);
+        });
+
+        it('should return metadata value', () => {
+            assert.equal(value, expectedValue);
+        });
+    });
+
+    describe('isRenamedIdentifier (identifierNode: ESTree.Identifier): boolean', () => {
+        const expectedValue: boolean = true;
+
+        let node: ESTree.Identifier,
+            value: boolean | undefined;
+
+        before(() => {
+            node = NodeFactory.identifierNode('foo');
+            node.metadata = {};
+            node.metadata.renamedIdentifier = true;
+            value = NodeMetadata.isRenamedIdentifier(node);
+        });
+
+        it('should return metadata value', () => {
+            assert.equal(value, expectedValue);
+        });
+    });
+
+    describe('isReplacedLiteral (literalNode: ESTree.Literal): boolean', () => {
+        const expectedValue: boolean = true;
+
+        let node: ESTree.Literal,
+            value: boolean | undefined;
+
+        before(() => {
+            node = NodeFactory.literalNode('foo');
+            node.metadata = {};
+            node.metadata.replacedLiteral = true;
+            value = NodeMetadata.isReplacedLiteral(node);
+        });
+
+        it('should return metadata value', () => {
+            assert.equal(value, expectedValue);
+        });
+    });
+});

+ 115 - 117
test/unit-tests/node/node-utils/NodeUtils.spec.ts

@@ -4,7 +4,7 @@ import { assert } from 'chai';
 
 import { TStatement } from '../../../../src/types/node/TStatement';
 
-import { Nodes } from '../../../../src/node/Nodes';
+import { NodeFactory } from '../../../../src/node/NodeFactory';
 import { NodeUtils } from '../../../../src/node/NodeUtils';
 
 describe('NodeUtils', () => {
@@ -13,10 +13,10 @@ describe('NodeUtils', () => {
             expectedLiteralNode: ESTree.Literal;
 
         before(() => {
-            literalNode = Nodes.getLiteralNode('value');
+            literalNode = NodeFactory.literalNode('value');
             delete literalNode['x-verbatim-property'];
 
-            expectedLiteralNode = Nodes.getLiteralNode('value');
+            expectedLiteralNode = NodeFactory.literalNode('value');
 
             NodeUtils.addXVerbatimPropertyToLiterals(literalNode);
         });
@@ -33,40 +33,40 @@ describe('NodeUtils', () => {
 
             before(() => {
                 // actual AST tree
-                const expressionStatementNode1: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-                const expressionStatementNode2: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
+                const expressionStatementNode1: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+                const expressionStatementNode2: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
 
-                const ifStatementBlockStatementNode1: ESTree.BlockStatement = Nodes.getBlockStatementNode([
+                const ifStatementBlockStatementNode1: ESTree.BlockStatement = NodeFactory.blockStatementNode([
                     expressionStatementNode1,
                     expressionStatementNode2
                 ]);
 
-                const ifStatementNode1: ESTree.IfStatement = Nodes.getIfStatementNode(
-                    Nodes.getLiteralNode(true),
+                const ifStatementNode1: ESTree.IfStatement = NodeFactory.ifStatementNode(
+                    NodeFactory.literalNode(true),
                     ifStatementBlockStatementNode1
                 );
 
                 // expected AST tree
-                const expressionStatementNode3: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-                const expressionStatementNode4: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
+                const expressionStatementNode3: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+                const expressionStatementNode4: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
 
-                const ifStatementBlockStatementNode2: ESTree.BlockStatement = Nodes.getBlockStatementNode([
+                const ifStatementBlockStatementNode2: ESTree.BlockStatement = NodeFactory.blockStatementNode([
                     expressionStatementNode3,
                     expressionStatementNode4
                 ]);
 
-                const ifStatementNode2: ESTree.IfStatement = Nodes.getIfStatementNode(
-                    Nodes.getLiteralNode(true),
+                const ifStatementNode2: ESTree.IfStatement = NodeFactory.ifStatementNode(
+                    NodeFactory.literalNode(true),
                     ifStatementBlockStatementNode2
                 );
 
                 programNode = NodeUtils.clone(
-                    Nodes.getProgramNode([
+                    NodeFactory.programNode([
                         ifStatementNode1
                     ])
                 );
                 expectedProgramNode = NodeUtils.parentize(
-                    Nodes.getProgramNode([
+                    NodeFactory.programNode([
                         ifStatementNode2
                     ])
                 );
@@ -83,34 +83,34 @@ describe('NodeUtils', () => {
 
             before(() => {
                 // actual AST tree
-                const arrayExpressionNode: ESTree.ArrayExpression = Nodes.getArrayExpressionNode([
-                    Nodes.getLiteralNode(1),
-                    Nodes.getLiteralNode(2),
+                const arrayExpressionNode: ESTree.ArrayExpression = NodeFactory.arrayExpressionNode([
+                    NodeFactory.literalNode(1),
+                    NodeFactory.literalNode(2),
                     <any>null,
-                    Nodes.getLiteralNode(4)
+                    NodeFactory.literalNode(4)
                 ]);
-                const expressionStatementNode: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(
+                const expressionStatementNode: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(
                     arrayExpressionNode
                 );
 
                 // expected AST tree
-                const expectedArrayExpressionNode: ESTree.ArrayExpression = Nodes.getArrayExpressionNode([
-                    Nodes.getLiteralNode(1),
-                    Nodes.getLiteralNode(2),
+                const expectedArrayExpressionNode: ESTree.ArrayExpression = NodeFactory.arrayExpressionNode([
+                    NodeFactory.literalNode(1),
+                    NodeFactory.literalNode(2),
                     <any>null,
-                    Nodes.getLiteralNode(4)
+                    NodeFactory.literalNode(4)
                 ]);
-                const expectedExpressionStatementNode: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(
+                const expectedExpressionStatementNode: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(
                     expectedArrayExpressionNode
                 );
 
                 programNode = NodeUtils.clone(
-                    Nodes.getProgramNode([
+                    NodeFactory.programNode([
                         expressionStatementNode
                     ])
                 );
                 expectedProgramNode = NodeUtils.parentize(
-                    Nodes.getProgramNode([
+                    NodeFactory.programNode([
                         expectedExpressionStatementNode
                     ])
                 );
@@ -122,7 +122,7 @@ describe('NodeUtils', () => {
         });
     });
 
-    describe('convertCodeToStructure (code: string): ESTree.Node[]', () => {
+    describe('convertCodeToStructure (code: string): ESTree.Statement[]', () => {
         let structure: TStatement[],
             expectedStructure: TStatement[];
 
@@ -131,15 +131,13 @@ describe('NodeUtils', () => {
                 var abc = 'cde';
             `;
 
-            const identifierNode: ESTree.Identifier = Nodes.getIdentifierNode('abc');
-            const literalNode: ESTree.Literal = Nodes.getLiteralNode('cde');
-            const variableDeclaratorNode: ESTree.VariableDeclarator = Nodes.getVariableDeclaratorNode(identifierNode, literalNode);
-            const variableDeclarationNode: ESTree.VariableDeclaration = Nodes.getVariableDeclarationNode([
-                variableDeclaratorNode
-            ]);
-            const programNode: ESTree.Program = Nodes.getProgramNode([
-                variableDeclarationNode
-            ]);
+            const identifierNode: ESTree.Identifier = NodeFactory.identifierNode('abc');
+            const literalNode: ESTree.Literal = NodeFactory.literalNode('cde');
+            const variableDeclaratorNode: ESTree.VariableDeclarator = NodeFactory
+                .variableDeclaratorNode(identifierNode, literalNode);
+            const variableDeclarationNode: ESTree.VariableDeclaration = NodeFactory
+                .variableDeclarationNode([variableDeclaratorNode]);
+            const programNode: ESTree.Program = NodeFactory.programNode([variableDeclarationNode]);
 
             programNode.parentNode = programNode;
             variableDeclarationNode.parentNode = programNode;
@@ -162,11 +160,11 @@ describe('NodeUtils', () => {
 
         before(() => {
             structure = [
-                Nodes.getProgramNode([
-                    Nodes.getVariableDeclarationNode([
-                        Nodes.getVariableDeclaratorNode(
-                            Nodes.getIdentifierNode('abc'),
-                            Nodes.getLiteralNode('cde')
+                NodeFactory.programNode([
+                    NodeFactory.variableDeclarationNode([
+                        NodeFactory.variableDeclaratorNode(
+                            NodeFactory.identifierNode('abc'),
+                            NodeFactory.literalNode('cde')
                         )
                     ])
                 ])
@@ -192,37 +190,37 @@ describe('NodeUtils', () => {
             programNode: ESTree.Program;
 
         before(() => {
-            expressionStatementNode1 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-            expressionStatementNode2 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-            expressionStatementNode3 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
+            expressionStatementNode1 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode2 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode3 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
 
-            ifStatementBlockStatementNode2 = Nodes.getBlockStatementNode([
+            ifStatementBlockStatementNode2 = NodeFactory.blockStatementNode([
                 expressionStatementNode2,
                 expressionStatementNode3
             ]);
 
-            ifStatementNode2 = Nodes.getIfStatementNode(
-                Nodes.getLiteralNode(true),
+            ifStatementNode2 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
                 ifStatementBlockStatementNode2
             );
 
-            ifStatementBlockStatementNode1 = Nodes.getBlockStatementNode([
+            ifStatementBlockStatementNode1 = NodeFactory.blockStatementNode([
                 ifStatementNode2
             ]);
 
-            ifStatementNode1 = Nodes.getIfStatementNode(
-                Nodes.getLiteralNode(true),
+            ifStatementNode1 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
                 ifStatementBlockStatementNode1
             );
 
-            functionDeclarationBlockStatementNode = Nodes.getBlockStatementNode([
+            functionDeclarationBlockStatementNode = NodeFactory.blockStatementNode([
                 expressionStatementNode1,
                 ifStatementNode1
             ]);
 
-            functionDeclarationNode = Nodes.getFunctionDeclarationNode('test', [], functionDeclarationBlockStatementNode);
+            functionDeclarationNode = NodeFactory.functionDeclarationNode('test', [], functionDeclarationBlockStatementNode);
 
-            programNode = Nodes.getProgramNode([
+            programNode = NodeFactory.programNode([
                 functionDeclarationNode
             ]);
 
@@ -301,17 +299,17 @@ describe('NodeUtils', () => {
                 statementNode3: ESTree.Statement;
 
             before(() => {
-                statementNode1 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('a')
+                statementNode1 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('a')
                 );
-                statementNode2 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('b')
+                statementNode2 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('b')
                 );
-                statementNode3 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('c')
+                statementNode3 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('c')
                 );
 
-                const blockStatementNode: ESTree.BlockStatement = Nodes.getBlockStatementNode([
+                const blockStatementNode: ESTree.BlockStatement = NodeFactory.blockStatementNode([
                     statementNode1,
                     statementNode2,
                     statementNode3
@@ -341,18 +339,18 @@ describe('NodeUtils', () => {
                 statementNode3: ESTree.Statement;
 
             before(() => {
-                statementNode1 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('a')
+                statementNode1 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('a')
                 );
-                statementNode2 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('b')
+                statementNode2 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('b')
                 );
-                statementNode3 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('c')
+                statementNode3 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('c')
                 );
 
-                const switchCaseNode: ESTree.SwitchCase = Nodes.getSwitchCaseNode(
-                    Nodes.getLiteralNode(true),
+                const switchCaseNode: ESTree.SwitchCase = NodeFactory.switchCaseNode(
+                    NodeFactory.literalNode(true),
                     [
                         statementNode1,
                         statementNode2,
@@ -386,17 +384,17 @@ describe('NodeUtils', () => {
                 statementNode3: ESTree.Statement;
 
             before(() => {
-                statementNode1 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('a')
+                statementNode1 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('a')
                 );
-                statementNode2 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('b')
+                statementNode2 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('b')
                 );
-                statementNode3 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('c')
+                statementNode3 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('c')
                 );
 
-                const blockStatementNode: ESTree.BlockStatement = Nodes.getBlockStatementNode([
+                const blockStatementNode: ESTree.BlockStatement = NodeFactory.blockStatementNode([
                     statementNode1,
                     statementNode2,
                     statementNode3
@@ -426,18 +424,18 @@ describe('NodeUtils', () => {
                 statementNode3: ESTree.Statement;
 
             before(() => {
-                statementNode1 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('a')
+                statementNode1 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('a')
                 );
-                statementNode2 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('b')
+                statementNode2 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('b')
                 );
-                statementNode3 = Nodes.getExpressionStatementNode(
-                    Nodes.getIdentifierNode('c')
+                statementNode3 = NodeFactory.expressionStatementNode(
+                    NodeFactory.identifierNode('c')
                 );
 
-                const switchCaseNode: ESTree.SwitchCase = Nodes.getSwitchCaseNode(
-                    Nodes.getLiteralNode(true),
+                const switchCaseNode: ESTree.SwitchCase = NodeFactory.switchCaseNode(
+                    NodeFactory.literalNode(true),
                     [
                         statementNode1,
                         statementNode2,
@@ -481,59 +479,59 @@ describe('NodeUtils', () => {
             programNode: ESTree.Program;
 
         before(() => {
-            expressionStatementNode1 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-            expressionStatementNode2 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-            expressionStatementNode3 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
+            expressionStatementNode1 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode2 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode3 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
 
-            ifStatementBlockStatementNode3 = Nodes.getBlockStatementNode([
+            ifStatementBlockStatementNode3 = NodeFactory.blockStatementNode([
                 expressionStatementNode2,
                 expressionStatementNode3
             ]);
 
-            ifStatementNode3 = Nodes.getIfStatementNode(
-                Nodes.getLiteralNode(true),
+            ifStatementNode3 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
                 ifStatementBlockStatementNode3
             );
 
-            ifStatementBlockStatementNode2 = Nodes.getBlockStatementNode();
+            ifStatementBlockStatementNode2 = NodeFactory.blockStatementNode();
 
-            ifStatementBlockStatementNode1 = Nodes.getBlockStatementNode([
+            ifStatementBlockStatementNode1 = NodeFactory.blockStatementNode([
                 ifStatementNode3
             ]);
 
-            ifStatementNode2 = Nodes.getIfStatementNode(
-                Nodes.getLiteralNode(true),
+            ifStatementNode2 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
                 ifStatementBlockStatementNode2
             );
 
-            ifStatementNode1 = Nodes.getIfStatementNode(
-                Nodes.getLiteralNode(true),
+            ifStatementNode1 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
                 ifStatementBlockStatementNode1
             );
 
-            switchCaseNode = Nodes.getSwitchCaseNode(
-                Nodes.getLiteralNode(1),
+            switchCaseNode = NodeFactory.switchCaseNode(
+                NodeFactory.literalNode(1),
                 [
                     ifStatementNode2
                 ]
             );
 
-            switchStatementNode = Nodes.getSwitchStatementNode(
-                Nodes.getLiteralNode(1),
+            switchStatementNode = NodeFactory.switchStatementNode(
+                NodeFactory.literalNode(1),
                 [
                     switchCaseNode
                 ]
             );
 
-            functionDeclarationBlockStatementNode = Nodes.getBlockStatementNode([
+            functionDeclarationBlockStatementNode = NodeFactory.blockStatementNode([
                 expressionStatementNode1,
                 ifStatementNode1,
                 switchStatementNode
             ]);
 
-            functionDeclarationNode = Nodes.getFunctionDeclarationNode('test', [], functionDeclarationBlockStatementNode);
+            functionDeclarationNode = NodeFactory.functionDeclarationNode('test', [], functionDeclarationBlockStatementNode);
 
-            programNode = Nodes.getProgramNode([
+            programNode = NodeFactory.programNode([
                 functionDeclarationNode
             ]);
 
@@ -610,11 +608,11 @@ describe('NodeUtils', () => {
             unaryExpressionArgumentNode: ESTree.Node;
 
         before(() => {
-            const literalNode: ESTree.Literal = Nodes.getLiteralNode('test');
-            const unaryExpressionNode2: ESTree.UnaryExpression = Nodes.getUnaryExpressionNode('!', literalNode);
-            const unaryExpressionNode1: ESTree.UnaryExpression = Nodes.getUnaryExpressionNode('!', unaryExpressionNode2);
-            const expressionStatementNode: ESTree.ExpressionStatement = Nodes.getExpressionStatementNode(unaryExpressionNode1);
-            const programNode: ESTree.Program = Nodes.getProgramNode([
+            const literalNode: ESTree.Literal = NodeFactory.literalNode('test');
+            const unaryExpressionNode2: ESTree.UnaryExpression = NodeFactory.unaryExpressionNode('!', literalNode);
+            const unaryExpressionNode1: ESTree.UnaryExpression = NodeFactory.unaryExpressionNode('!', unaryExpressionNode2);
+            const expressionStatementNode: ESTree.ExpressionStatement = NodeFactory.expressionStatementNode(unaryExpressionNode1);
+            const programNode: ESTree.Program = NodeFactory.programNode([
                 expressionStatementNode
             ]);
 
@@ -641,23 +639,23 @@ describe('NodeUtils', () => {
             programNode: ESTree.Program;
 
         beforeEach(() => {
-            expressionStatementNode1 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
-            expressionStatementNode2 = Nodes.getExpressionStatementNode(Nodes.getIdentifierNode('identifier'));
+            expressionStatementNode1 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode2 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
 
-            ifStatementBlockStatementNode = Nodes.getBlockStatementNode([
+            ifStatementBlockStatementNode = NodeFactory.blockStatementNode([
                 expressionStatementNode1,
                 expressionStatementNode2
             ]);
 
-            ifStatementNode = Nodes.getIfStatementNode(
-                Nodes.getLiteralNode(true),
+            ifStatementNode = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
                 ifStatementBlockStatementNode
             );
         });
 
         describe('Variant #1: parentize AST-tree with `ProgramNode` as root node', () => {
             beforeEach(() => {
-                programNode = Nodes.getProgramNode([
+                programNode = NodeFactory.programNode([
                     ifStatementNode
                 ]);
 
@@ -710,8 +708,8 @@ describe('NodeUtils', () => {
 
     describe('parentizeNode <T extends ESTree.Node = ESTree.Program> (node: T, parentNode: ESTree.Node): T', () => {
         describe('Variant #1: node with parent node', () => {
-            const identifier: ESTree.Identifier = Nodes.getIdentifierNode('foo');
-            const breakStatement: ESTree.BreakStatement = Nodes.getBreakStatement(identifier);
+            const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
+            const breakStatement: ESTree.BreakStatement = NodeFactory.breakStatement(identifier);
 
             const expectedResult: ESTree.Identifier = NodeUtils.clone(identifier);
 
@@ -729,7 +727,7 @@ describe('NodeUtils', () => {
         });
 
         describe('Variant #2: node without parent node', () => {
-            const identifier: ESTree.Identifier = Nodes.getIdentifierNode('Foo');
+            const identifier: ESTree.Identifier = NodeFactory.identifierNode('Foo');
             const expectedResult: ESTree.Identifier = NodeUtils.clone(identifier);
 
             let result: ESTree.Identifier;

+ 18 - 17
test/unit-tests/storages/ArrayStorage.spec.ts

@@ -2,15 +2,16 @@ import { assert } from 'chai';
 
 import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
 
+import { IArrayStorage } from '../../../src/interfaces/storages/IArrayStorage';
 import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
 import { IOptions } from '../../../src/interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../src/interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../src/interfaces/storages/IStorage';
+
 
 import { ArrayStorage } from '../../../src/storages/ArrayStorage';
 import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
 
-class ConcreteStorage extends ArrayStorage <string> {
+class ConcreteStorage <V> extends ArrayStorage <V> {
     constructor () {
         const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
 
@@ -24,10 +25,10 @@ class ConcreteStorage extends ArrayStorage <string> {
 }
 
 /**
- * @type {IStorage<any>}
+ * @returns {IArrayStorage<V>}
  */
-const getStorageInstance = (): IStorage <any> => {
-    const storage: IStorage<any> = new ConcreteStorage();
+const getStorageInstance = <V> (): IArrayStorage <V> => {
+    const storage: IArrayStorage <V> = new ConcreteStorage <V> ();
 
     storage.initialize();
 
@@ -38,7 +39,7 @@ describe('ArrayStorage', () => {
     const storageKey: number = 0;
     const storageValue: string = 'foo';
 
-    let storage: IStorage <any>;
+    let storage: IArrayStorage <any>;
 
     describe('initialize (...args: any[]): void', () => {
         const expectedError: ErrorConstructor = Error;
@@ -46,7 +47,7 @@ describe('ArrayStorage', () => {
         let testFunc: () => void;
 
         before(() => {
-            storage = new ConcreteStorage();
+            storage = new ConcreteStorage<string>();
             testFunc = () => storage.set(storageKey, storageValue);
         });
 
@@ -61,7 +62,7 @@ describe('ArrayStorage', () => {
         let arrayStorage: string[];
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
 
             arrayStorage = storage.getStorage();
         });
@@ -78,7 +79,7 @@ describe('ArrayStorage', () => {
             let value: string;
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, storageValue);
 
                 value = storage.get(storageKey);
@@ -95,7 +96,7 @@ describe('ArrayStorage', () => {
             let testFunc: () => void;
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
 
                 testFunc = () => storage.get(storageKey);
             });
@@ -112,7 +113,7 @@ describe('ArrayStorage', () => {
         let storageLength: number;
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
             storage.set(storageKey, storageValue);
 
             storageLength = storage.getLength();
@@ -128,7 +129,7 @@ describe('ArrayStorage', () => {
 
         describe('Variant #1', () => {
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, storageValue);
 
                 key = storage.getKeyOf(storageValue);
@@ -145,7 +146,7 @@ describe('ArrayStorage', () => {
             };
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, object);
 
                 key = storage.getKeyOf(object);
@@ -163,7 +164,7 @@ describe('ArrayStorage', () => {
             };
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, object);
 
                 key = storage.getKeyOf({...object});
@@ -179,7 +180,7 @@ describe('ArrayStorage', () => {
         let value: string;
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
             storage.set(storageKey, storageValue);
 
             value = storage.get(storageKey);
@@ -199,10 +200,10 @@ describe('ArrayStorage', () => {
         let array: string[];
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
             storage.set(storageKey, storageValue);
 
-            const secondStorage: IStorage <string> = getStorageInstance();
+            const secondStorage: IArrayStorage <string> = getStorageInstance<string>();
             secondStorage.set(secondStorageKey, secondStorageValue);
 
             storage.mergeWith(secondStorage, false);

+ 22 - 22
test/unit-tests/storages/MapStorage.spec.ts

@@ -3,14 +3,14 @@ import { assert } from 'chai';
 import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
 
 import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+import { IMapStorage } from '../../../src/interfaces/storages/IMapStorage';
 import { IOptions } from '../../../src/interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../src/interfaces/utils/IRandomGenerator';
-import { IStorage } from '../../../src/interfaces/storages/IStorage';
 
 import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
 import { MapStorage } from '../../../src/storages/MapStorage';
 
-class ConcreteStorage extends MapStorage <string> {
+class ConcreteStorage <V> extends MapStorage <string, V> {
     constructor () {
         const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
 
@@ -24,10 +24,10 @@ class ConcreteStorage extends MapStorage <string> {
 }
 
 /**
- * @type {IStorage<any>}
+ * @returns {IMapStorage<string, V>}
  */
-const getStorageInstance = (): IStorage <any> => {
-    const storage: IStorage<any> = new ConcreteStorage();
+const getStorageInstance = <V>(): IMapStorage <string, V> => {
+    const storage: IMapStorage <string, V> = new ConcreteStorage <V> ();
 
     storage.initialize();
 
@@ -38,7 +38,7 @@ describe('MapStorage', () => {
     const storageKey: string = 'foo';
     const storageValue: string = 'bar';
 
-    let storage: IStorage <any>;
+    let storage: IMapStorage <string, any>;
 
     describe('initialize (...args: any[]): void', () => {
         const expectedError: ErrorConstructor = Error;
@@ -55,13 +55,13 @@ describe('MapStorage', () => {
         });
     });
 
-    describe('getStorage (): Map <string | number, T>', () => {
+    describe('getStorage (): Map <K, V>', () => {
         const expectedInstanceOf: MapConstructor = Map;
 
-        let mapStorage: string[];
+        let mapStorage: Map <string, string>;
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
 
             mapStorage = storage.getStorage();
         });
@@ -71,14 +71,14 @@ describe('MapStorage', () => {
         });
     });
 
-    describe('get (key: string | number): T', () => {
+    describe('get (key: K): V', () => {
         describe('Variant #1: value exist', () => {
             const expectedValue: string = storageValue;
 
             let value: string;
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, storageValue);
 
                 value = storage.get(storageKey);
@@ -95,7 +95,7 @@ describe('MapStorage', () => {
             let testFunc: () => void;
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
 
                 testFunc = () => storage.get(storageKey);
             });
@@ -112,7 +112,7 @@ describe('MapStorage', () => {
         let storageLength: number;
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
             storage.set(storageKey, storageValue);
 
             storageLength = storage.getLength();
@@ -123,12 +123,12 @@ describe('MapStorage', () => {
         });
     });
 
-    describe('getKeyOf (value: T): string | number | null', () => {
+    describe('getKeyOf (value: V): K | null', () => {
         let key: string | number | null;
 
         describe('Variant #1', () => {
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, storageValue);
 
                 key = storage.getKeyOf(storageValue);
@@ -145,7 +145,7 @@ describe('MapStorage', () => {
             };
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, object);
 
                 key = storage.getKeyOf(object);
@@ -163,7 +163,7 @@ describe('MapStorage', () => {
             };
 
             before(() => {
-                storage = getStorageInstance();
+                storage = getStorageInstance<string>();
                 storage.set(storageKey, object);
 
                 key = storage.getKeyOf({...object});
@@ -175,11 +175,11 @@ describe('MapStorage', () => {
         });
     });
 
-    describe('set (key: string | number, value: T): void', () => {
+    describe('set (key: K, value: V): void', () => {
         let value: string;
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
             storage.set(storageKey, storageValue);
 
             value = storage.get(storageKey);
@@ -202,15 +202,15 @@ describe('MapStorage', () => {
         let array: string[][];
 
         before(() => {
-            storage = getStorageInstance();
+            storage = getStorageInstance<string>();
             storage.set(storageKey, storageValue);
 
-            const secondStorage: IStorage <string> = getStorageInstance();
+            const secondStorage: IMapStorage <string, string> = getStorageInstance<string>();
             secondStorage.set(secondStorageKey, secondStorageValue);
 
             storage.mergeWith(secondStorage, false);
 
-            array = <any>Array.from(storage.getStorage());
+            array = Array.from(storage.getStorage());
         });
 
         it('should merge two storages', () => {

+ 1 - 0
webpack.config.js

@@ -50,6 +50,7 @@ module.exports = {
                 loader: 'awesome-typescript-loader',
                 query: {
                     useBabel: true,
+                    babelCore: '@babel/core',
                     useCache: true,
                     forceIsolatedModules: true
                 }

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 401 - 390
yarn.lock


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.