Browse Source

Merge remote-tracking branch 'origin/dead-code-injection' into dead-code-injection

# Conflicts:
#	dist/index.js
#	src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
sanex3339 8 years ago
parent
commit
7a20082465
46 changed files with 1090 additions and 678 deletions
  1. 9 4
      README.md
  2. 336 308
      dist/index.js
  3. 8 8
      package.json
  4. 2 0
      src/container/InversifyContainerFacade.ts
  5. 2 0
      src/container/ServiceIdentifiers.ts
  6. 10 0
      src/container/modules/custom-nodes/CustomNodesModule.ts
  7. 5 0
      src/container/modules/node-transformers/ControlFlowTransformersModule.ts
  8. 33 0
      src/container/modules/node-transformers/DeadCodeInjectionTransformersModule.ts
  9. 45 0
      src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts
  10. 61 0
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts
  11. 2 1
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  12. 2 1
      src/enums/container/ControlFlowReplacers.ts
  13. 3 1
      src/enums/container/CustomNodes.ts
  14. 3 0
      src/enums/container/DeadCodeInjectionReplacers.ts
  15. 13 0
      src/interfaces/node-transformers/IDeadCodeInjectionReplacer.d.ts
  16. 6 1
      src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts
  17. 1 1
      src/node-transformers/control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts
  18. 93 0
      src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts
  19. 43 2
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
  20. 41 0
      src/node-transformers/dead-code-injection-transformers/dead-code-injection-replacers/AbstractDeadCodeInjectionReplacer.ts
  21. 33 0
      src/node-transformers/dead-code-injection-transformers/dead-code-injection-replacers/IfStatementDeadCodeInjectionReplacer.ts
  22. 3 29
      src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts
  23. 1 1
      src/options/presets/Default.ts
  24. 1 1
      src/options/presets/NoCustomNodes.ts
  25. 5 0
      src/types/container/TDeadCodeInjectionReplacerFactory.d.ts
  26. 1 1
      src/utils/CryptUtils.ts
  27. 19 76
      test/dev/dev.ts
  28. 9 3
      test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts
  29. 14 9
      test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts
  30. 17 15
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts
  31. 3 3
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec.ts
  32. 4 4
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec.ts
  33. 4 4
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec.ts
  34. 33 0
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/StringLiteralControlFlowReplacer.spec.ts
  35. 3 0
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/fixtures/input-1.js
  36. 6 6
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts
  37. 3 3
      test/functional-tests/node-transformers/converting-transformers/member-expression-transformer/MemberExpressionTransformer.spec.ts
  38. 2 2
      test/functional-tests/node-transformers/converting-transformers/method-definition-transformer/MethodDefinitionTransformer.spec.ts
  39. 1 1
      test/functional-tests/node-transformers/obfuscating-transformers/catch-clause-transformer/CatchClauseTransformer.spec.ts
  40. 1 1
      test/functional-tests/node-transformers/obfuscating-transformers/function-transformer/FunctionTransformer.spec.ts
  41. 38 38
      test/functional-tests/node-transformers/obfuscating-transformers/literal-transformer/LiteralTransformer.spec.ts
  42. 3 14
      test/functional-tests/node-transformers/obfuscating-transformers/object-expression-transformer/ObjectExpressionTransformer.spec.ts
  43. 16 16
      test/functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts
  44. 1 0
      test/index.spec.ts
  45. 1 1
      webpack.config.js
  46. 150 123
      yarn.lock

+ 9 - 4
README.md

@@ -192,7 +192,7 @@ Following options are available for the JS Obfuscator:
     stringArray: true,
     stringArray: true,
     stringArrayEncoding: false,
     stringArrayEncoding: false,
     stringArrayThreshold: 0.75,
     stringArrayThreshold: 0.75,
-    unicodeEscapeSequence: true
+    unicodeEscapeSequence: false
 }
 }
 ```
 ```
 
 
@@ -449,11 +449,11 @@ This setting is especially useful for large code size because it repeatedly call
 `stringArrayThreshold: 0` equals to `stringArray: false`.
 `stringArrayThreshold: 0` equals to `stringArray: false`.
 
 
 ### `unicodeEscapeSequence`
 ### `unicodeEscapeSequence`
-Type: `boolean` Default: `true`
+Type: `boolean` Default: `false`
 
 
 Allows to enable/disable string conversion to unicode escape sequence.
 Allows to enable/disable string conversion to unicode escape sequence.
 
 
-Unicode escape sequence increases code size greatly. It is recommended to disable this option when using [`stringArrayEncoding`](#stringarrayencoding) (especially with `rc4` encoding).
+Unicode escape sequence increases code size greatly and strings easily can be reverted to their original view. Recommended to enable this option only for small source code. 
 
 
 ## Preset Options
 ## Preset Options
 ### High obfuscation, low performance
 ### High obfuscation, low performance
@@ -465,6 +465,8 @@ Performance will 50-100% slower than without obfuscation
     compact: true,
     compact: true,
     controlFlowFlattening: true,
     controlFlowFlattening: true,
     controlFlowFlatteningThreshold: 1,
     controlFlowFlatteningThreshold: 1,
+    deadCodeInjection: true,
+	deadCodeInjectionThreshold: 1,
     debugProtection: true,
     debugProtection: true,
     debugProtectionInterval: true,
     debugProtectionInterval: true,
     disableConsoleOutput: true,
     disableConsoleOutput: true,
@@ -486,6 +488,8 @@ Performance will 30-35% slower than without obfuscation
     compact: true,
     compact: true,
     controlFlowFlattening: true,
     controlFlowFlattening: true,
     controlFlowFlatteningThreshold: 0.75,
     controlFlowFlatteningThreshold: 0.75,
+    deadCodeInjection: true,
+    deadCodeInjectionThreshold: 0.75,
     debugProtection: false,
     debugProtection: false,
     debugProtectionInterval: false,
     debugProtectionInterval: false,
     disableConsoleOutput: true,
     disableConsoleOutput: true,
@@ -506,6 +510,7 @@ Performance will slightly slower than without obfuscation
 {
 {
     compact: true,
     compact: true,
     controlFlowFlattening: false,
     controlFlowFlattening: false,
+    deadCodeInjection: false,
     debugProtection: false,
     debugProtection: false,
     debugProtectionInterval: false,
     debugProtectionInterval: false,
     disableConsoleOutput: true,
     disableConsoleOutput: true,
@@ -514,7 +519,7 @@ Performance will slightly slower than without obfuscation
     stringArray: true,
     stringArray: true,
     stringArrayEncoding: false,
     stringArrayEncoding: false,
     stringArrayThreshold: 0.75,
     stringArrayThreshold: 0.75,
-    unicodeEscapeSequence: true
+    unicodeEscapeSequence: false
 }
 }
 ```
 ```
 
 

File diff suppressed because it is too large
+ 336 - 308
dist/index.js


+ 8 - 8
package.json

@@ -20,15 +20,15 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "chance": "1.0.6",
     "chance": "1.0.6",
-    "class-validator": "0.6.8",
+    "class-validator": "0.7.0",
     "commander": "2.9.0",
     "commander": "2.9.0",
     "escodegen": "1.8.1",
     "escodegen": "1.8.1",
     "esprima": "3.1.3",
     "esprima": "3.1.3",
     "estraverse": "4.2.0",
     "estraverse": "4.2.0",
-    "inversify": "3.1.0",
+    "inversify": "3.3.0",
     "mkdirp": "0.5.1",
     "mkdirp": "0.5.1",
     "reflect-metadata": "0.1.10",
     "reflect-metadata": "0.1.10",
-    "source-map-support": "0.4.13",
+    "source-map-support": "0.4.14",
     "string-template": "1.0.0",
     "string-template": "1.0.0",
     "tslib": "1.6.0"
     "tslib": "1.6.0"
   },
   },
@@ -42,8 +42,8 @@
     "@types/estree": "0.0.34",
     "@types/estree": "0.0.34",
     "@types/mkdirp": "0.3.29",
     "@types/mkdirp": "0.3.29",
     "@types/mocha": "2.2.40",
     "@types/mocha": "2.2.40",
-    "@types/node": "7.0.8",
-    "@types/sinon": "1.16.35",
+    "@types/node": "7.0.10",
+    "@types/sinon": "1.16.36",
     "@types/string-template": "1.0.2",
     "@types/string-template": "1.0.2",
     "awesome-typescript-loader": "3.1.2",
     "awesome-typescript-loader": "3.1.2",
     "babel-cli": "6.24.0",
     "babel-cli": "6.24.0",
@@ -54,12 +54,12 @@
     "coveralls": "2.12.0",
     "coveralls": "2.12.0",
     "istanbul": "1.1.0-alpha.1",
     "istanbul": "1.1.0-alpha.1",
     "mocha": "3.2.0",
     "mocha": "3.2.0",
-    "sinon": "2.0.0",
-    "ts-node": "2.1.0",
+    "sinon": "2.1.0",
+    "ts-node": "3.0.2",
     "tslint": "4.5.1",
     "tslint": "4.5.1",
     "tslint-loader": "3.4.3",
     "tslint-loader": "3.4.3",
     "typescript": "2.2.0",
     "typescript": "2.2.0",
-    "webpack": "2.2.1",
+    "webpack": "2.3.1",
     "webpack-node-externals": "1.5.4"
     "webpack-node-externals": "1.5.4"
   },
   },
   "repository": {
   "repository": {

+ 2 - 0
src/container/InversifyContainerFacade.ts

@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from './ServiceIdentifiers';
 
 
 import { controlFlowTransformersModule } from './modules/node-transformers/ControlFlowTransformersModule';
 import { controlFlowTransformersModule } from './modules/node-transformers/ControlFlowTransformersModule';
 import { customNodesModule } from './modules/custom-nodes/CustomNodesModule';
 import { customNodesModule } from './modules/custom-nodes/CustomNodesModule';
+import { deadCodeInjectionTransformersModule } from './modules/node-transformers/DeadCodeInjectionTransformersModule';
 import { obfuscatingTransformersModule } from './modules/node-transformers/ObfuscatingTransformersModule';
 import { obfuscatingTransformersModule } from './modules/node-transformers/ObfuscatingTransformersModule';
 import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
 import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
 import { stackTraceAnalyzerModule } from './modules/stack-trace-analyzer/StackTraceAnalyzerModule';
 import { stackTraceAnalyzerModule } from './modules/stack-trace-analyzer/StackTraceAnalyzerModule';
@@ -88,6 +89,7 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
         this.container.load(customNodesModule);
         this.container.load(customNodesModule);
         this.container.load(nodeTransformersModule);
         this.container.load(nodeTransformersModule);
         this.container.load(controlFlowTransformersModule);
         this.container.load(controlFlowTransformersModule);
+        this.container.load(deadCodeInjectionTransformersModule);
         this.container.load(obfuscatingTransformersModule);
         this.container.load(obfuscatingTransformersModule);
     }
     }
 
 

+ 2 - 0
src/container/ServiceIdentifiers.ts

@@ -3,6 +3,7 @@ export const ServiceIdentifiers: any = {
     Factory__IControlFlowReplacer: Symbol('Factory<IControlFlowReplacer>'),
     Factory__IControlFlowReplacer: Symbol('Factory<IControlFlowReplacer>'),
     Factory__ICustomNode: Symbol('Factory<ICustomNode>'),
     Factory__ICustomNode: Symbol('Factory<ICustomNode>'),
     Factory__ICustomNodeGroup: Symbol('Factory<ICustomNodeGroup>'),
     Factory__ICustomNodeGroup: Symbol('Factory<ICustomNodeGroup>'),
+    Factory__IDeadCodeInjectionReplacer: Symbol('Factory<IDeadCodeInjectionReplacer>'),
     Factory__INodeTransformer: Symbol('Factory<INodeTransformer[]>'),
     Factory__INodeTransformer: Symbol('Factory<INodeTransformer[]>'),
     Factory__IObfuscationResult: Symbol('Factory<IObfuscationResult>'),
     Factory__IObfuscationResult: Symbol('Factory<IObfuscationResult>'),
     Factory__IObfuscationReplacer: Symbol('Factory<IObfuscationReplacer>'),
     Factory__IObfuscationReplacer: Symbol('Factory<IObfuscationReplacer>'),
@@ -10,6 +11,7 @@ export const ServiceIdentifiers: any = {
     ICalleeDataExtractor: Symbol('ICalleeDataExtractor'),
     ICalleeDataExtractor: Symbol('ICalleeDataExtractor'),
     ICustomNodeGroup: Symbol('ICustomNodeGroup'),
     ICustomNodeGroup: Symbol('ICustomNodeGroup'),
     IControlFlowReplacer: Symbol('IControlFlowReplacer'),
     IControlFlowReplacer: Symbol('IControlFlowReplacer'),
+    IDeadCodeInjectionReplacer: Symbol('IDeadCodeInjectionReplacer'),
     IJavaScriptObfuscator: Symbol('IJavaScriptObfuscator'),
     IJavaScriptObfuscator: Symbol('IJavaScriptObfuscator'),
     INodeTransformer: Symbol('INodeTransformer'),
     INodeTransformer: Symbol('INodeTransformer'),
     IObfuscationEventEmitter: Symbol('IObfuscationEventEmitter'),
     IObfuscationEventEmitter: Symbol('IObfuscationEventEmitter'),

+ 10 - 0
src/container/modules/custom-nodes/CustomNodesModule.ts

@@ -31,6 +31,8 @@ import { SelfDefendingUnicodeNode } from '../../../custom-nodes/self-defending-n
 import { StringArrayCallsWrapper } from '../../../custom-nodes/string-array-nodes/StringArrayCallsWrapper';
 import { StringArrayCallsWrapper } from '../../../custom-nodes/string-array-nodes/StringArrayCallsWrapper';
 import { StringArrayNode } from '../../../custom-nodes/string-array-nodes/StringArrayNode';
 import { StringArrayNode } from '../../../custom-nodes/string-array-nodes/StringArrayNode';
 import { StringArrayRotateFunctionNode } from '../../../custom-nodes/string-array-nodes/StringArrayRotateFunctionNode';
 import { StringArrayRotateFunctionNode } from '../../../custom-nodes/string-array-nodes/StringArrayRotateFunctionNode';
+import { StringLiteralControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode';
+import { StringLiteralNode } from '../../../custom-nodes/control-flow-flattening-nodes/StringLiteralNode';
 
 
 export const customNodesModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
 export const customNodesModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // custom nodes
     // custom nodes
@@ -102,6 +104,14 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .toConstructor(StringArrayRotateFunctionNode)
         .toConstructor(StringArrayRotateFunctionNode)
         .whenTargetNamed(CustomNodes.StringArrayRotateFunctionNode);
         .whenTargetNamed(CustomNodes.StringArrayRotateFunctionNode);
 
 
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(StringLiteralControlFlowStorageCallNode)
+        .whenTargetNamed(CustomNodes.StringLiteralControlFlowStorageCallNode);
+
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(StringLiteralNode)
+        .whenTargetNamed(CustomNodes.StringLiteralNode);
+
     // node groups
     // node groups
     bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
     bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
         .to(ConsoleOutputCustomNodeGroup)
         .to(ConsoleOutputCustomNodeGroup)

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

@@ -8,6 +8,7 @@ import { ControlFlowReplacers } from '../../../enums/container/ControlFlowReplac
 import { BinaryExpressionControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer';
 import { BinaryExpressionControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer';
 import { CallExpressionControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer';
 import { CallExpressionControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer';
 import { LogicalExpressionControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer';
 import { LogicalExpressionControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer';
+import { StringLiteralControlFlowReplacer } from '../../../node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer';
 
 
 export const controlFlowTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
 export const controlFlowTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
     bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
@@ -22,6 +23,10 @@ export const controlFlowTransformersModule: interfaces.ContainerModule = new Con
         .to(LogicalExpressionControlFlowReplacer)
         .to(LogicalExpressionControlFlowReplacer)
         .whenTargetNamed(ControlFlowReplacers.LogicalExpressionControlFlowReplacer);
         .whenTargetNamed(ControlFlowReplacers.LogicalExpressionControlFlowReplacer);
 
 
+    bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
+        .to(StringLiteralControlFlowReplacer)
+        .whenTargetNamed(ControlFlowReplacers.StringLiteralControlFlowReplacer);
+
     bind<IControlFlowReplacer>(ServiceIdentifiers.Factory__IControlFlowReplacer)
     bind<IControlFlowReplacer>(ServiceIdentifiers.Factory__IControlFlowReplacer)
         .toFactory<IControlFlowReplacer>((context: interfaces.Context) => {
         .toFactory<IControlFlowReplacer>((context: interfaces.Context) => {
             const cache: Map <ControlFlowReplacers, IControlFlowReplacer> = new Map();
             const cache: Map <ControlFlowReplacers, IControlFlowReplacer> = new Map();

+ 33 - 0
src/container/modules/node-transformers/DeadCodeInjectionTransformersModule.ts

@@ -0,0 +1,33 @@
+import { ContainerModule, interfaces } from 'inversify';
+import { ServiceIdentifiers } from '../../ServiceIdentifiers';
+
+import { IDeadCodeInjectionReplacer } from '../../../interfaces/node-transformers/IDeadCodeInjectionReplacer';
+import { IfStatementDeadCodeInjectionReplacer } from '../../../node-transformers/dead-code-injection-transformers/dead-code-injection-replacers/IfStatementDeadCodeInjectionReplacer';
+
+import { DeadCodeInjectionReplacers } from '../../../enums/container/DeadCodeInjectionReplacers';
+
+export const deadCodeInjectionTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
+    bind<IDeadCodeInjectionReplacer>(ServiceIdentifiers.IDeadCodeInjectionReplacer)
+        .to(IfStatementDeadCodeInjectionReplacer)
+        .whenTargetNamed(DeadCodeInjectionReplacers.IfStatementDeadCodeInjectionReplacer);
+
+    bind<IDeadCodeInjectionReplacer>(ServiceIdentifiers.Factory__IDeadCodeInjectionReplacer)
+        .toFactory<IDeadCodeInjectionReplacer>((context: interfaces.Context) => {
+            const cache: Map <DeadCodeInjectionReplacers, IDeadCodeInjectionReplacer> = new Map();
+
+            return (replacerName: DeadCodeInjectionReplacers) => {
+                if (cache.has(replacerName)) {
+                    return <IDeadCodeInjectionReplacer>cache.get(replacerName);
+                }
+
+                const deadCodeInjectionReplacer: IDeadCodeInjectionReplacer = context.container.getNamed<IDeadCodeInjectionReplacer>(
+                    ServiceIdentifiers.IDeadCodeInjectionReplacer,
+                    replacerName
+                );
+
+                cache.set(replacerName, deadCodeInjectionReplacer);
+
+                return deadCodeInjectionReplacer;
+            };
+        });
+});

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

@@ -0,0 +1,45 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import { TStatement } from '../../types/node/TStatement';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+
+import { initializable } from '../../decorators/Initializable';
+
+import { AbstractCustomNode } from '../AbstractCustomNode';
+import { Nodes } from '../../node/Nodes';
+
+@injectable()
+export class StringLiteralNode extends AbstractCustomNode {
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private literalValue: string;
+
+    /**
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(options);
+    }
+
+    /**
+     * @param literalValue
+     */
+    public initialize (literalValue: string): void {
+        this.literalValue = literalValue;
+    }
+
+    /**
+     * @returns {TStatement[]}
+     */
+    protected getNodeStructure (): TStatement[] {
+        const structure: TStatement = <any>Nodes.getLiteralNode(this.literalValue);
+
+        return [structure];
+    }
+}

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

@@ -0,0 +1,61 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import { TStatement } from '../../../types/node/TStatement';
+
+import { IOptions } from '../../../interfaces/options/IOptions';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { AbstractCustomNode } from '../../AbstractCustomNode';
+import { Nodes } from '../../../node/Nodes';
+import { NodeUtils } from '../../../node/NodeUtils';
+
+@injectable()
+export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode {
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private controlFlowStorageKey: string;
+
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private controlFlowStorageName: string;
+
+    /**
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(options);
+    }
+
+    /**
+     * @param controlFlowStorageName
+     * @param controlFlowStorageKey
+     */
+    public initialize (
+        controlFlowStorageName: string,
+        controlFlowStorageKey: string
+    ): void {
+        this.controlFlowStorageName = controlFlowStorageName;
+        this.controlFlowStorageKey = controlFlowStorageKey;
+    }
+
+    protected getNodeStructure (): TStatement[] {
+        const structure: TStatement = Nodes.getExpressionStatementNode(
+            Nodes.getMemberExpressionNode(
+                Nodes.getIdentifierNode(this.controlFlowStorageName),
+                Nodes.getIdentifierNode(this.controlFlowStorageKey)
+            )
+        );
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
+    }
+}

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

@@ -60,7 +60,8 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
             }),
             }),
             {
             {
                 ...NO_CUSTOM_NODES_PRESET,
                 ...NO_CUSTOM_NODES_PRESET,
-                seed: this.options.seed
+                seed: this.options.seed,
+                unicodeEscapeSequence: true
             }
             }
         ).getObfuscatedCode();
         ).getObfuscatedCode();
     }
     }

+ 2 - 1
src/enums/container/ControlFlowReplacers.ts

@@ -1,5 +1,6 @@
 export enum ControlFlowReplacers {
 export enum ControlFlowReplacers {
     BinaryExpressionControlFlowReplacer,
     BinaryExpressionControlFlowReplacer,
     CallExpressionControlFlowReplacer,
     CallExpressionControlFlowReplacer,
-    LogicalExpressionControlFlowReplacer
+    LogicalExpressionControlFlowReplacer,
+    StringLiteralControlFlowReplacer,
 }
 }

+ 3 - 1
src/enums/container/CustomNodes.ts

@@ -15,5 +15,7 @@ export enum CustomNodes {
     SelfDefendingUnicodeNode,
     SelfDefendingUnicodeNode,
     StringArrayCallsWrapper,
     StringArrayCallsWrapper,
     StringArrayNode,
     StringArrayNode,
-    StringArrayRotateFunctionNode
+    StringArrayRotateFunctionNode,
+    StringLiteralControlFlowStorageCallNode,
+    StringLiteralNode,
 }
 }

+ 3 - 0
src/enums/container/DeadCodeInjectionReplacers.ts

@@ -0,0 +1,3 @@
+export enum DeadCodeInjectionReplacers {
+    IfStatementDeadCodeInjectionReplacer
+}

+ 13 - 0
src/interfaces/node-transformers/IDeadCodeInjectionReplacer.d.ts

@@ -0,0 +1,13 @@
+import * as ESTree from 'estree';
+
+export interface IDeadCodeInjectionReplacer {
+    /**
+     * @param node
+     * @param parentNode
+     * @returns ESTree.Node
+     */
+    replace (
+        node: ESTree.Node,
+        parentNode: ESTree.Node
+    ): ESTree.Node;
+}

+ 6 - 1
src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -32,7 +32,8 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     private static readonly controlFlowReplacersMap: Map <string, ControlFlowReplacers> = new Map([
     private static readonly controlFlowReplacersMap: Map <string, ControlFlowReplacers> = new Map([
         [NodeType.BinaryExpression, ControlFlowReplacers.BinaryExpressionControlFlowReplacer],
         [NodeType.BinaryExpression, ControlFlowReplacers.BinaryExpressionControlFlowReplacer],
         [NodeType.CallExpression, ControlFlowReplacers.CallExpressionControlFlowReplacer],
         [NodeType.CallExpression, ControlFlowReplacers.CallExpressionControlFlowReplacer],
-        [NodeType.LogicalExpression, ControlFlowReplacers.LogicalExpressionControlFlowReplacer]
+        [NodeType.LogicalExpression, ControlFlowReplacers.LogicalExpressionControlFlowReplacer],
+        [NodeType.Literal, ControlFlowReplacers.StringLiteralControlFlowReplacer]
     ]);
     ]);
 
 
     /**
     /**
@@ -220,6 +221,10 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
                 const controlFlowReplacerName: ControlFlowReplacers = <ControlFlowReplacers>FunctionControlFlowTransformer
                 const controlFlowReplacerName: ControlFlowReplacers = <ControlFlowReplacers>FunctionControlFlowTransformer
                     .controlFlowReplacersMap.get(node.type);
                     .controlFlowReplacersMap.get(node.type);
 
 
+                if (controlFlowReplacerName === undefined) {
+                    return node;
+                }
+
                 return {
                 return {
                     ...this.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage),
                     ...this.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage),
                     parentNode
                     parentNode

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

@@ -88,7 +88,7 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
         const storageKeysForCurrentId: string[] | undefined = storageKeysById.get(replacerId);
         const storageKeysForCurrentId: string[] | undefined = storageKeysById.get(replacerId);
 
 
         if (
         if (
-            RandomGeneratorUtils.getMathRandom() > usingExistingIdentifierChance &&
+            RandomGeneratorUtils.getMathRandom() < usingExistingIdentifierChance &&
             storageKeysForCurrentId &&
             storageKeysForCurrentId &&
             storageKeysForCurrentId.length
             storageKeysForCurrentId.length
         ) {
         ) {

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

@@ -0,0 +1,93 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
+import { TStatement } from '../../../types/node/TStatement';
+
+import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IStorage } from '../../../interfaces/storages/IStorage';
+
+import { CustomNodes } from '../../../enums/container/CustomNodes';
+
+import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { Node } from '../../../node/Node';
+
+@injectable()
+export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplacer {
+    /**
+     * @type {number}
+     */
+    private static readonly usingExistingIdentifierChance: number = 1;
+
+    /**
+     * @param customNodeFactory
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(customNodeFactory, options);
+    }
+
+    /**
+     * @param literalNode
+     * @param parentNode
+     * @param controlFlowStorage
+     * @returns {ESTree.Node}
+     */
+    public replace (
+        literalNode: ESTree.Literal,
+        parentNode: ESTree.Node,
+        controlFlowStorage: IStorage <ICustomNode>
+    ): ESTree.Node {
+        if (Node.isPropertyNode(parentNode) && parentNode.key === literalNode) {
+            return literalNode;
+        }
+
+        if (typeof literalNode.value !== 'string' || literalNode.value.length < 3) {
+            return literalNode;
+        }
+
+        const replacerId: string = String(literalNode.value);
+        const literalFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.StringLiteralNode);
+
+        literalFunctionCustomNode.initialize(literalNode.value);
+
+        const storageKey: string = this.insertCustomNodeToControlFlowStorage(
+            literalFunctionCustomNode,
+            controlFlowStorage,
+            replacerId,
+            StringLiteralControlFlowReplacer.usingExistingIdentifierChance
+        );
+
+        return this.getControlFlowStorageCallNode(controlFlowStorage.getStorageId(), storageKey);
+    }
+
+    /**
+     * @param controlFlowStorageId
+     * @param storageKey
+     * @returns {ESTree.Node}
+     */
+    protected getControlFlowStorageCallNode (
+        controlFlowStorageId: string,
+        storageKey: string
+    ): ESTree.Node {
+        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
+            CustomNodes.StringLiteralControlFlowStorageCallNode
+        );
+
+        controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey);
+
+        const statementNode: TStatement = controlFlowStorageCallCustomNode.getNode()[0];
+
+        if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
+            throw new Error(`\`controlFlowStorageCallCustomNode.getNode()[0]\` should returns array with \`ExpressionStatement\` node`);
+        }
+
+        return statementNode.expression;
+    }
+}

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

@@ -1,11 +1,16 @@
 import { injectable, inject } from 'inversify';
 import { injectable, inject } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
+import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
+import { TDeadCodeInjectionReplacerFactory } from '../../types/container/TDeadCodeInjectionReplacerFactory';
+
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IVisitor } from '../../interfaces/IVisitor';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 
+import { DeadCodeInjectionReplacers } from '../../enums/container/DeadCodeInjectionReplacers';
+
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
 import { Node } from '../../node/Node';
 import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
@@ -13,12 +18,28 @@ import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 @injectable()
 @injectable()
 export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
 export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
     /**
     /**
+     * @type {DeadCodeInjectionReplacers[]}
+     */
+    private static readonly deadCodeInjectionReplacersList: DeadCodeInjectionReplacers[] = [
+        DeadCodeInjectionReplacers.IfStatementDeadCodeInjectionReplacer
+    ];
+
+    /**
+     * @type {TDeadCodeInjectionReplacerFactory}
+     */
+    private deadCodeInjectionReplacerFactory: TDeadCodeInjectionReplacerFactory;
+
+    /**
+     * @param deadCodeInjectionReplacerFactory
      * @param options
      * @param options
      */
      */
     constructor (
     constructor (
+        @inject(ServiceIdentifiers.Factory__IDeadCodeInjectionReplacer) deadCodeInjectionReplacerFactory: TDeadCodeInjectionReplacerFactory,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
         super(options);
         super(options);
+
+        this.deadCodeInjectionReplacerFactory = deadCodeInjectionReplacerFactory;
     }
     }
 
 
     /**
     /**
@@ -47,8 +68,28 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
             return blockStatementNode;
             return blockStatementNode;
         }
         }
 
 
-        const blockStatementBody: ESTree.Statement[] = blockStatementNode.body;
+        this.transformBlockStatementNode(blockStatementNode);
 
 
-        return blockStatementBody[0];
+        return blockStatementNode;
+    }
+
+    /**
+     * @param blockStatementNode
+     */
+    private transformBlockStatementNode (blockStatementNode: ESTree.BlockStatement): void {
+        estraverse.replace(blockStatementNode, {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
+                let newNode: ESTree.Node = node;
+
+                DeadCodeInjectionTransformer.deadCodeInjectionReplacersList.forEach((replacerName: DeadCodeInjectionReplacers) => {
+                    newNode = {
+                        ...this.deadCodeInjectionReplacerFactory(replacerName).replace(node, parentNode),
+                        parentNode
+                    };
+                });
+
+                return newNode;
+            }
+        });
     }
     }
 }
 }

+ 41 - 0
src/node-transformers/dead-code-injection-transformers/dead-code-injection-replacers/AbstractDeadCodeInjectionReplacer.ts

@@ -0,0 +1,41 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
+
+import { IDeadCodeInjectionReplacer } from '../../../interfaces/node-transformers/IDeadCodeInjectionReplacer';
+import { IOptions } from '../../../interfaces/options/IOptions';
+
+@injectable()
+export abstract class AbstractDeadCodeInjectionReplacer implements IDeadCodeInjectionReplacer {
+    /**
+     * @type {TCustomNodeFactory}
+     */
+    protected readonly customNodeFactory: TCustomNodeFactory;
+
+    /**
+     * @type {IOptions}
+     */
+    protected readonly options: IOptions;
+
+    /**
+     * @param customNodeFactory
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        this.customNodeFactory = customNodeFactory;
+        this.options = options;
+    }
+
+    /**
+     * @param node
+     * @param parentNode
+     * @returns {ESTree.Node}
+     */
+    public abstract replace (node: ESTree.Node, parentNode: ESTree.Node): ESTree.Node;
+}

+ 33 - 0
src/node-transformers/dead-code-injection-transformers/dead-code-injection-replacers/IfStatementDeadCodeInjectionReplacer.ts

@@ -0,0 +1,33 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
+
+import { IOptions } from '../../../interfaces/options/IOptions';
+
+import { AbstractDeadCodeInjectionReplacer } from './AbstractDeadCodeInjectionReplacer';
+
+@injectable()
+export class IfStatementDeadCodeInjectionReplacer extends AbstractDeadCodeInjectionReplacer {
+    /**
+     * @param customNodeFactory
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(customNodeFactory, options);
+    }
+
+    /**
+     * @param ifStatementNode
+     * @param parentNode
+     * @returns {ESTree.Node}
+     */
+    public replace (ifStatementNode: ESTree.IfStatement, parentNode: ESTree.Node): ESTree.Node {
+        return ifStatementNode;
+    }
+}

+ 3 - 29
src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts

@@ -1,7 +1,6 @@
 import { injectable, inject } from 'inversify';
 import { injectable, inject } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import * as escodegen from 'escodegen';
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
@@ -11,17 +10,13 @@ import { NodeType } from '../../enums/NodeType';
 
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
 import { Node } from '../../node/Node';
-import { Utils } from '../../utils/Utils';
 
 
 /**
 /**
  * replaces:
  * replaces:
- *     var object = { 'PSEUDO': 1 };
- *
- * or:
  *     var object = { PSEUDO: 1 };
  *     var object = { PSEUDO: 1 };
  *
  *
  * on:
  * on:
- *     var object = { '\u0050\u0053\u0045\u0055\u0044\u004f': 1 };
+ *     var object = { 'PSEUDO': 1 };
  */
  */
 @injectable()
 @injectable()
 export class ObjectExpressionTransformer extends AbstractNodeTransformer {
 export class ObjectExpressionTransformer extends AbstractNodeTransformer {
@@ -34,21 +29,6 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
         super(options);
         super(options);
     }
     }
 
 
-    /**
-     * @param node
-     * @returns {ESTree.Literal}
-     */
-    private static transformLiteralPropertyKey (node: ESTree.Literal): ESTree.Literal {
-        if (typeof node.value === 'string' && !node['x-verbatim-property']) {
-            node['x-verbatim-property'] = {
-                content : `'${Utils.stringToUnicodeEscapeSequence(node.value)}'`,
-                precedence: escodegen.Precedence.Primary
-            };
-        }
-
-        return node;
-    }
-
     /**
     /**
      * @param node
      * @param node
      * @returns {ESTree.Literal}
      * @returns {ESTree.Literal}
@@ -57,11 +37,7 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
         return {
         return {
             type: NodeType.Literal,
             type: NodeType.Literal,
             value: node.name,
             value: node.name,
-            raw: `'${node.name}'`,
-            'x-verbatim-property': {
-                content : `'${Utils.stringToUnicodeEscapeSequence(node.name)}'`,
-                precedence: escodegen.Precedence.Primary
-            }
+            raw: `'${node.name}'`
         };
         };
     }
     }
 
 
@@ -90,9 +66,7 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
                     property.shorthand = false;
                     property.shorthand = false;
                 }
                 }
 
 
-                if (Node.isLiteralNode(property.key)) {
-                    property.key = ObjectExpressionTransformer.transformLiteralPropertyKey(property.key);
-                } else if (Node.isIdentifierNode(property.key)) {
+                if (Node.isIdentifierNode(property.key)) {
                     property.key = ObjectExpressionTransformer.transformIdentifierPropertyKey(property.key);
                     property.key = ObjectExpressionTransformer.transformIdentifierPropertyKey(property.key);
                 }
                 }
             });
             });

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

@@ -23,5 +23,5 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
     stringArray: true,
     stringArray: true,
     stringArrayEncoding: false,
     stringArrayEncoding: false,
     stringArrayThreshold: 0.75,
     stringArrayThreshold: 0.75,
-    unicodeEscapeSequence: true
+    unicodeEscapeSequence: false
 });
 });

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

@@ -23,5 +23,5 @@ export const NO_CUSTOM_NODES_PRESET: TInputOptions = Object.freeze({
     stringArray: false,
     stringArray: false,
     stringArrayEncoding: false,
     stringArrayEncoding: false,
     stringArrayThreshold: 0,
     stringArrayThreshold: 0,
-    unicodeEscapeSequence: true
+    unicodeEscapeSequence: false
 });
 });

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

@@ -0,0 +1,5 @@
+import { IDeadCodeInjectionReplacer } from '../../interfaces/node-transformers/IDeadCodeInjectionReplacer';
+
+import { DeadCodeInjectionReplacers } from '../../enums/container/DeadCodeInjectionReplacers';
+
+export type TDeadCodeInjectionReplacerFactory = (replacer: DeadCodeInjectionReplacers) => IDeadCodeInjectionReplacer;

+ 1 - 1
src/utils/CryptUtils.ts

@@ -16,7 +16,7 @@ export class CryptUtils {
         });
         });
 
 
         for (
         for (
-            let block: number|undefined, charCode: number, idx: number = 0, map: string = chars;
+            let block: number | undefined, charCode: number, idx: number = 0, map: string = chars;
             string.charAt(idx | 0) || (map = '=', idx % 1);
             string.charAt(idx | 0) || (map = '=', idx % 1);
             output += map.charAt(63 & block >> 8 - idx % 1 * 8)
             output += map.charAt(63 & block >> 8 - idx % 1 * 8)
         ) {
         ) {

+ 19 - 76
test/dev/dev.ts

@@ -7,88 +7,31 @@ import { NO_CUSTOM_NODES_PRESET } from '../../src/options/presets/NoCustomNodes'
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
         `
             (function(){
             (function(){
-                var result = 1,
-                    term1 = 0,
-                    term2 = 1,
-                    i = 1;
-                while(i < 10)
-                {
-                    var test = 10;
-                    result = term1 + term2;
-                    console.log(result);
-                    term1 = term2;
-                    term2 = result;
-                    i++;
-                }
-        
-                console.log(test);
-                
-                var test = function (test) {
-                    console.log(test);
-                    
-                    if (true) {
-                        var test = 5
-                    }
-                    
-                    return test;
-                }
-                
-                console.log(test(1));
-                
-                function test2 (abc) {
-                    function test1 () {
-                      console.log('inside', abc.item);
-                    }
-                    
-                    console.log('тест', abc);
-                    
-                    var abc = {};
-                    
-                    return abc.item = 15, test1();
-                };
-                
-                var regexptest = /version\\/(\\d+)/i;
-                console.log(regexptest);
-                
-                test2(22);
-                console.log(105.4);
-                console.log(true, false);
-                
-                var sA = 'shorthand1';
-                var sB = 'shorthand2';
-                
-                console.log({sA, sB});
-                
-                try {
-                } catch (error) {
-                    console.log(error);
-                }
-                
-                function foo () {
-                    return function () {
-                        var sum1 = 10 + 20;
-                        var sum2 = 20 + 30;
-                        var sum3 = 30 + 50;
-                        var sub = sum3 - sum2;
-                        
-                        return sum1 + sub;
-                    }
-                }
-                
-                console.log(foo()());
-                
                 if (true) {
                 if (true) {
-                    console.log(\`1\`);
-                    console.log(\`2\`);
-                    console.log(\`3\`);
-                    console.log(\`4\`);
-                    console.log(\`5\`);
+                    var foo = function () {
+                        console.log('abc');
+                        console.log('cde');
+                        console.log('efg');
+                        console.log('hij');
+                        console.log('klm');
+                        console.log('nop');
+                        console.log('qrs');
+                        console.log('tuv');
+                        console.log('wxy');
+                        console.log('w');
+                    };
+                
+                    foo();
                 }
                 }
             })();
             })();
         `,
         `,
         {
         {
             ...NO_CUSTOM_NODES_PRESET,
             ...NO_CUSTOM_NODES_PRESET,
-            compact: false
+            compact: false,
+            stringArray: true,
+            stringArrayThreshold: 1,
+            deadCodeInjection: true,
+            deadCodeInjectionThreshold: 1
         }
         }
     ).getObfuscatedCode();
     ).getObfuscatedCode();
 
 

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

@@ -9,7 +9,9 @@ import { readFileAsString } from '../../../helpers/readFileAsString';
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
 
 describe('ConsoleOutputDisableExpressionNode', () => {
 describe('ConsoleOutputDisableExpressionNode', () => {
-    const regExp = /(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*)*'\]\['(\\x[a-f0-9]*)*'\] *= *_0x([a-f0-9]){4,6};){7}/u;
+    const consoleLogRegExp: RegExp = /_0x([a-f0-9]){4,6}\['console'\]\['log'\] *= *_0x([a-f0-9]){4,6};/u;
+    const consoleErrorRegExp: RegExp = /_0x([a-f0-9]){4,6}\['console'\]\['error'\] *= *_0x([a-f0-9]){4,6};/u;
+    const consoleWarnRegExp: RegExp = /_0x([a-f0-9]){4,6}\['console'\]\['warn'\] *= *_0x([a-f0-9]){4,6};/u;
 
 
     it('should correctly append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is set', () => {
     it('should correctly append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
@@ -20,7 +22,9 @@ describe('ConsoleOutputDisableExpressionNode', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(), regExp);
+        assert.match(obfuscationResult.getObfuscatedCode(), consoleLogRegExp);
+        assert.match(obfuscationResult.getObfuscatedCode(), consoleErrorRegExp);
+        assert.match(obfuscationResult.getObfuscatedCode(), consoleWarnRegExp);
     });
     });
 
 
     it('should\'t append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is not set', () => {
     it('should\'t append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is not set', () => {
@@ -33,6 +37,8 @@ describe('ConsoleOutputDisableExpressionNode', () => {
             }
             }
         );
         );
 
 
-        assert.notMatch(obfuscationResult.getObfuscatedCode(), regExp);
+        assert.notMatch(obfuscationResult.getObfuscatedCode(), consoleLogRegExp);
+        assert.notMatch(obfuscationResult.getObfuscatedCode(), consoleErrorRegExp);
+        assert.notMatch(obfuscationResult.getObfuscatedCode(), consoleWarnRegExp);
     });
     });
 });
 });

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

@@ -117,9 +117,9 @@ describe('JavaScriptObfuscator', () => {
             );
             );
         });
         });
 
 
-        it('should obfuscate simple code with literal variable value', () => {
-            let pattern1: RegExp = /^var _0x(\w){4} *= *\['(\\[x|u]\d+)+'\];/,
-                pattern2: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/,
+        it('should obfuscate simple code with latin literal variable value', () => {
+            let stringArrayLatinRegExp: RegExp = /^var _0x(\w){4} *= *\['abc'\];/,
+                stringArrayCallRegExp: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/,
                 obfuscatedCode1: string = JavaScriptObfuscator.obfuscate(
                 obfuscatedCode1: string = JavaScriptObfuscator.obfuscate(
                     readFileAsString(__dirname + '/fixtures/simple-input-2.js'),
                     readFileAsString(__dirname + '/fixtures/simple-input-2.js'),
                     {
                     {
@@ -127,7 +127,15 @@ describe('JavaScriptObfuscator', () => {
                         stringArray: true,
                         stringArray: true,
                         stringArrayThreshold: 1
                         stringArrayThreshold: 1
                     }
                     }
-                ).getObfuscatedCode(),
+                ).getObfuscatedCode();
+
+            assert.match(obfuscatedCode1, stringArrayLatinRegExp);
+            assert.match(obfuscatedCode1, stringArrayCallRegExp);
+        });
+
+        it('should obfuscate simple code with cyrillic literal variable value', () => {
+            let stringArrayCyrillicRegExp: RegExp = /^var _0x(\w){4} *= *\['(\\u\d+)+'\];/,
+                stringArrayCallRegExp: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/,
                 obfuscatedCode2: string = JavaScriptObfuscator.obfuscate(
                 obfuscatedCode2: string = JavaScriptObfuscator.obfuscate(
                     readFileAsString(__dirname + '/fixtures/simple-input-cyrillic.js'),
                     readFileAsString(__dirname + '/fixtures/simple-input-cyrillic.js'),
                     {
                     {
@@ -137,11 +145,8 @@ describe('JavaScriptObfuscator', () => {
                     }
                     }
                 ).getObfuscatedCode();
                 ).getObfuscatedCode();
 
 
-            assert.match(obfuscatedCode1, pattern1);
-            assert.match(obfuscatedCode1, pattern2);
-
-            assert.match(obfuscatedCode2, pattern1);
-            assert.match(obfuscatedCode2, pattern2);
+            assert.match(obfuscatedCode2, stringArrayCyrillicRegExp);
+            assert.match(obfuscatedCode2, stringArrayCallRegExp);
         });
         });
 
 
         it('should returns same code every time with same `seed`', function () {
         it('should returns same code every time with same `seed`', function () {

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

@@ -10,14 +10,16 @@ import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscator';
 
 
 describe('BlockStatementControlFlowTransformer', () => {
 describe('BlockStatementControlFlowTransformer', () => {
     describe('transformNode (blockStatementNode: ESTree.BlockStatement): ESTree.Node', () => {
     describe('transformNode (blockStatementNode: ESTree.BlockStatement): ESTree.Node', () => {
+        const switchCaseMapStringRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
+        const switchCaseMapVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\\x7c'\)/;
+
         describe('variant #1: 5 simple statements', () => {
         describe('variant #1: 5 simple statements', () => {
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 readFileAsString(__dirname + '/fixtures/input-1.js'),
                 readFileAsString(__dirname + '/fixtures/input-1.js'),
                 {
                 {
                     ...NO_CUSTOM_NODES_PRESET,
                     ...NO_CUSTOM_NODES_PRESET,
                     controlFlowFlattening: true,
                     controlFlowFlattening: true,
-                    controlFlowFlatteningThreshold: 1,
-                    unicodeEscapeSequence: false
+                    controlFlowFlatteningThreshold: 1
                 }
                 }
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
@@ -32,9 +34,8 @@ describe('BlockStatementControlFlowTransformer', () => {
             const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
             const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
             const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
             const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
 
 
-            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *'(.*?)'/;
-            const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
-            const switchCaseMapMatch: string = switchCaseMapMatches[1];
+            const switchCaseMapStringMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapStringRegExp);
+            const switchCaseMapMatch: string = switchCaseMapStringMatches[1];
             const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
             const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
 
 
             it('should save all statements', () => {
             it('should save all statements', () => {
@@ -52,6 +53,7 @@ describe('BlockStatementControlFlowTransformer', () => {
 
 
             it('should create variable with order of switch cases sequence', () => {
             it('should create variable with order of switch cases sequence', () => {
                 assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
                 assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
+                assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
             });
             });
         });
         });
 
 
@@ -77,9 +79,8 @@ describe('BlockStatementControlFlowTransformer', () => {
             const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
             const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
             const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
             const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
 
 
-            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *'(.*?)'/;
-            const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
-            const switchCaseMapMatch: string = switchCaseMapMatches[1];
+            const switchCaseMapStringMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapStringRegExp);
+            const switchCaseMapMatch: string = switchCaseMapStringMatches[1];
             const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
             const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
 
 
             it('should save all statements', () => {
             it('should save all statements', () => {
@@ -97,6 +98,7 @@ describe('BlockStatementControlFlowTransformer', () => {
 
 
             it('should create variable with order of switch cases sequence', () => {
             it('should create variable with order of switch cases sequence', () => {
                 assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
                 assert.deepEqual(switchCaseMap, ['0', '1', '2', '3', '4']);
+                assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
             });
             });
         });
         });
 
 
@@ -111,7 +113,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *console\['(\\x[a-f0-9]*){3}'\]\(0x1\); *\} *\( *\) *\);$/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *console\['log'\]\(0x1\); *\} *\( *\) *\);$/;
 
 
             it('shouldn\'t transform block statement if statements length less than 5', () => {
             it('shouldn\'t transform block statement if statements length less than 5', () => {
                 assert.match(obfuscatedCode, statementRegExp);
                 assert.match(obfuscatedCode, statementRegExp);
@@ -129,7 +131,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *const *_0x([a-f0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *const *_0x([a-f0-9]){4,6} *= *0x1; *console\['log'\]\(0x1\);/;
 
 
             it('shouldn\'t transform block statement if block statement contain variable declaration with `const` kind', () => {
             it('shouldn\'t transform block statement if block statement contain variable declaration with `const` kind', () => {
                 assert.match(obfuscatedCode, statementRegExp);
                 assert.match(obfuscatedCode, statementRegExp);
@@ -147,7 +149,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *let *_0x([a-f0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *let *_0x([a-f0-9]){4,6} *= *0x1; *console\['log'\]\(0x1\);/;
 
 
             it('shouldn\'t transform block statement if block statement contain variable declaration with `let` kind', () => {
             it('shouldn\'t transform block statement if block statement contain variable declaration with `let` kind', () => {
                 assert.match(obfuscatedCode, statementRegExp);
                 assert.match(obfuscatedCode, statementRegExp);
@@ -165,7 +167,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *break; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *break; *console\['log'\]\(0x1\);/;
 
 
             it('shouldn\'t transform block statement if block statement contain break statement', () => {
             it('shouldn\'t transform block statement if block statement contain break statement', () => {
                 assert.match(obfuscatedCode, statementRegExp);
                 assert.match(obfuscatedCode, statementRegExp);
@@ -183,7 +185,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *continue; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *while *\(!!\[\]\) *\{ *continue; *console\['log'\]\(0x1\);/;
 
 
             it('shouldn\'t transform block statement if block statement contain continue statement', () => {
             it('shouldn\'t transform block statement if block statement contain continue statement', () => {
                 assert.match(obfuscatedCode, statementRegExp);
                 assert.match(obfuscatedCode, statementRegExp);
@@ -201,7 +203,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-f0-9]){4,6} *\( *\) *\{ *\} *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-f0-9]){4,6} *\( *\) *\{ *\} *console\['log'\]\(0x1\);/;
 
 
             it('shouldn\'t transform block statement if block statement contain function declaration', () => {
             it('shouldn\'t transform block statement if block statement contain function declaration', () => {
                 assert.match(obfuscatedCode, statementRegExp);
                 assert.match(obfuscatedCode, statementRegExp);
@@ -222,7 +224,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             );
 
 
             const regExp1: RegExp = /switch *\(_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\+\+\]\) *\{/g;
             const regExp1: RegExp = /switch *\(_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\+\+\]\) *\{/g;
-            const regExp2: RegExp = /\(function *\( *\) *\{ *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/g;
+            const regExp2: RegExp = /\(function *\( *\) *\{ *console\['log'\]\(0x1\);/g;
             const transformedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
             const transformedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
             const untouchedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;
             const untouchedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;
 
 

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

@@ -20,7 +20,7 @@ describe('BinaryExpressionControlFlowReplacer', () => {
                 }
                 }
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(0x1, *0x2\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{3}'\]\(0x1, *0x2\);/;
 
 
             it('should replace binary expression node by call to control flow storage node', () => {
             it('should replace binary expression node by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -47,8 +47,8 @@ describe('BinaryExpressionControlFlowReplacer', () => {
                         }
                         }
                     );
                     );
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(0x1, *0x2\);/;
-                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(0x2, *0x3\);/;
+                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{3}'\])\(0x1, *0x2\);/;
+                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{3}'\])\(0x2, *0x3\);/;
 
 
                     const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);

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

@@ -20,7 +20,7 @@ describe('CallExpressionControlFlowReplacer', () => {
                 }
                 }
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(_0x([a-f0-9]){4,6}, *0x1, *0x2\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{3}'\]\(_0x([a-f0-9]){4,6}, *0x1, *0x2\);/;
 
 
             it('should replace call expression node by call to control flow storage node', () => {
             it('should replace call expression node by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -47,8 +47,8 @@ describe('CallExpressionControlFlowReplacer', () => {
                         }
                         }
                     );
                     );
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(_0x([a-f0-9]){4,6}, *0x1, *0x2\);/;
-                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(_0x([a-f0-9]){4,6}, *0x2, *0x3\);/;
+                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{3}'\])\(_0x([a-f0-9]){4,6}, *0x1, *0x2\);/;
+                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{3}'\])\(_0x([a-f0-9]){4,6}, *0x2, *0x3\);/;
 
 
                     const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
@@ -78,7 +78,7 @@ describe('CallExpressionControlFlowReplacer', () => {
                 }
                 }
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\\x73\\x75\\x6d'\]\(0x1, *0x2\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['sum'\]\(0x1, *0x2\);/;
 
 
             it('shouldn\'t replace call expression node by call to control flow storage node if call expression callee is member expression node', () => {
             it('shouldn\'t replace call expression node by call to control flow storage node if call expression callee is member expression node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);

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

@@ -20,7 +20,7 @@ describe('LogicalExpressionControlFlowReplacer', () => {
                 }
                 }
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(!!\[\], *!\[\]\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{3}'\]\(!!\[\], *!\[\]\);/;
 
 
             it('should replace logical expression node by call to control flow storage node', () => {
             it('should replace logical expression node by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -47,8 +47,8 @@ describe('LogicalExpressionControlFlowReplacer', () => {
                         }
                         }
                     );
                     );
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(!!\[\], *!\[\]\);/;
-                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(!\[\], *!!\[\]\);/;
+                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{3}'\])\(!!\[\], *!\[\]\);/;
+                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{3}'\])\(!\[\], *!!\[\]\);/;
 
 
                     const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
@@ -78,7 +78,7 @@ describe('LogicalExpressionControlFlowReplacer', () => {
                 }
                 }
             );
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(!_0x([a-f0-9]){4,6}, *!_0x([a-f0-9]){4,6}\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{3}'\]\(!_0x([a-f0-9]){4,6}, *!_0x([a-f0-9]){4,6}\);/;
 
 
             it('should replace logical expression node with unary expression by call to control flow storage node', () => {
             it('should replace logical expression node with unary expression by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);

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

@@ -0,0 +1,33 @@
+import { assert } from 'chai';
+
+import { IObfuscationResult } from '../../../../../../src/interfaces/IObfuscationResult';
+
+import { NO_CUSTOM_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
+
+import { readFileAsString } from '../../../../../helpers/readFileAsString';
+
+import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscator';
+
+describe('StringLiteralControlFlowReplacer', () => {
+    describe('replace (literalNode: ESTree.Literal,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/input-1.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET,
+                controlFlowFlattening: true,
+                controlFlowFlatteningThreshold: 1
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+        const controlFlowStorageStringLiteralRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *\{'\w{3}' *: *'test'\};/;
+        const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{3}'\];/;
+
+        it('should add string literal node as property of control flow storage node', () => {
+            assert.match(obfuscatedCode, controlFlowStorageStringLiteralRegExp);
+        });
+
+        it('should replace string literal node by call to control flow storage node', () => {
+            assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
+        });
+    });
+});

+ 3 - 0
test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/fixtures/input-1.js

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

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

@@ -12,15 +12,15 @@ describe('FunctionControlFlowTransformer', () => {
     const variableMatch: string = '_0x([a-f0-9]){4,6}';
     const variableMatch: string = '_0x([a-f0-9]){4,6}';
     const rootControlFlowStorageNodeMatch: string = `` +
     const rootControlFlowStorageNodeMatch: string = `` +
         `var *${variableMatch} *= *\\{` +
         `var *${variableMatch} *= *\\{` +
-            `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
+            `'\\w{3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
                 `return *${variableMatch} *\\+ *${variableMatch};` +
                 `return *${variableMatch} *\\+ *${variableMatch};` +
             `\\}` +
             `\\}` +
         `\\};` +
         `\\};` +
     ``;
     ``;
     const innerControlFlowStorageNodeMatch: string = `` +
     const innerControlFlowStorageNodeMatch: string = `` +
         `var *${variableMatch} *= *\\{` +
         `var *${variableMatch} *= *\\{` +
-            `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
-                `return *${variableMatch}\\['(\\\\x[a-f0-9]*){3}'\\]\\(${variableMatch}, *${variableMatch}\\);` +
+            `'\\w{3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
+                `return *${variableMatch}\\['\\w{3}'\\]\\(${variableMatch}, *${variableMatch}\\);` +
             `\\}` +
             `\\}` +
         `\\};` +
         `\\};` +
     ``;
     ``;
@@ -95,10 +95,10 @@ describe('FunctionControlFlowTransformer', () => {
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const regexp: RegExp = new RegExp(
             const regexp: RegExp = new RegExp(
                 `var *${variableMatch} *= *\\{` +
                 `var *${variableMatch} *= *\\{` +
-                    `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
+                    `'\\w{3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
                         `return *${variableMatch} *\\+ *${variableMatch};` +
                         `return *${variableMatch} *\\+ *${variableMatch};` +
                     `\\}, *` +
                     `\\}, *` +
-                    `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
+                    `'\\w{3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
                         `return *${variableMatch} *- *${variableMatch};` +
                         `return *${variableMatch} *- *${variableMatch};` +
                     `\\}` +
                     `\\}` +
                 `\\};`
                 `\\};`
@@ -130,7 +130,7 @@ describe('FunctionControlFlowTransformer', () => {
             const expectedValue: number = 0;
             const expectedValue: number = 0;
             const regExp: RegExp = new RegExp(
             const regExp: RegExp = new RegExp(
                 `var *[a-zA-Z]{6} *= *\\{` +
                 `var *[a-zA-Z]{6} *= *\\{` +
-                    `'(\\\\x[a-f0-9]*){3}' *: *function *_0x[0-9] *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
+                    `'\\w{3}' *: *function *_0x[0-9] *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
                         `return *${variableMatch} *\\+ *${variableMatch};` +
                         `return *${variableMatch} *\\+ *${variableMatch};` +
                     `\\}` +
                     `\\}` +
                 `\\};`
                 `\\};`

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

@@ -18,7 +18,7 @@ describe('MemberExpressionTransformer', () => {
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\['\\x6c\\x6f\\x67'\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\['log'\];/);
         });
         });
 
 
         it('should replace member expression dot notation call by square brackets call to unicode array', () => {
         it('should replace member expression dot notation call by square brackets call to unicode array', () => {
@@ -31,7 +31,7 @@ describe('MemberExpressionTransformer', () => {
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['log'\];/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-f0-9]){4}\('0x0'\)\];/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-f0-9]){4}\('0x0'\)\];/);
         });
         });
     });
     });
@@ -47,7 +47,7 @@ describe('MemberExpressionTransformer', () => {
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['log'\];/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-f0-9]){4}\('0x0'\)\];/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-f0-9]){4}\('0x0'\)\];/);
         });
         });
 
 

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

@@ -19,7 +19,7 @@ describe('MethodDefinitionTransformer', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /\['\\x62\\x61\\x72'\]\(\)\{\}/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /\['bar'\]\(\)\{\}/);
     });
     });
 
 
     it('should replace method definition node `key` property with unicode array call', () => {
     it('should replace method definition node `key` property with unicode array call', () => {
@@ -32,7 +32,7 @@ describe('MethodDefinitionTransformer', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['\\x62\\x61\\x72'\];/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['bar'\];/);
         assert.match(obfuscationResult.getObfuscatedCode(),  /\[_0x([a-f0-9]){4}\('0x0'\)\]\(\)\{\}/);
         assert.match(obfuscationResult.getObfuscatedCode(),  /\[_0x([a-f0-9]){4}\('0x0'\)\]\(\)\{\}/);
     });
     });
 
 

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

@@ -18,7 +18,7 @@ describe('CatchClauseTransformer', () => {
         );
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
         const paramNameRegExp: RegExp = /catch *\((_0x([a-f0-9]){4,6})\) *\{/;
         const paramNameRegExp: RegExp = /catch *\((_0x([a-f0-9]){4,6})\) *\{/;
-        const bodyParamNameRegExp: RegExp = /console\['\\x6c\\x6f\\x67'\]\((_0x([a-f0-9]){4,6})\);/;
+        const bodyParamNameRegExp: RegExp = /console\['log'\]\((_0x([a-f0-9]){4,6})\);/;
 
 
         it('should transform catch clause node', () => {
         it('should transform catch clause node', () => {
             assert.match(obfuscatedCode, paramNameRegExp);
             assert.match(obfuscatedCode, paramNameRegExp);

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

@@ -22,7 +22,7 @@ describe('FunctionTransformer', () => {
             const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
             const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
                 .match(/var _0x[a-f0-9]{4,6} *= *function *\((_0x[a-f0-9]{4,6})\) *\{/);
                 .match(/var _0x[a-f0-9]{4,6} *= *function *\((_0x[a-f0-9]{4,6})\) *\{/);
             const functionBodyIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
             const functionBodyIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-f0-9]{4,6})\)/);
+                .match(/console\['log'\]\((_0x[a-f0-9]{4,6})\)/);
 
 
             const functionParamIdentifierName: string = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
             const functionParamIdentifierName: string = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
             const functionBodyIdentifierName: string = (<RegExpMatchArray>functionBodyIdentifierMatch)[1];
             const functionBodyIdentifierName: string = (<RegExpMatchArray>functionBodyIdentifierMatch)[1];

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

@@ -10,59 +10,55 @@ import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscator';
 
 
 describe('LiteralTransformer', () => {
 describe('LiteralTransformer', () => {
     describe('transformation of literal node with string value', () => {
     describe('transformation of literal node with string value', () => {
-        it('should replace literal node value with unicode escape sequence', () => {
+        it('should replace literal node value with value from string array', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 {
                 {
-                    ...NO_CUSTOM_NODES_PRESET
+                    ...NO_CUSTOM_NODES_PRESET,
+                    stringArray: true,
+                    stringArrayThreshold: 1
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /^var *test *= *'\\x74\\x65\\x73\\x74';$/);
+            assert.match(
+                obfuscationResult.getObfuscatedCode(),
+                /^var *_0x([a-f0-9]){4} *= *\['test'\];/
+            );
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
         });
         });
 
 
-        it('should replace literal node value with unicode escape sequence from string array', () => {
+        it('shouldn\'t replace literal node value with value from string array if `stringArray` option is disabled', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 {
                 {
-                    ...NO_CUSTOM_NODES_PRESET,
-                    stringArray: true,
-                    stringArrayThreshold: 1
+                    ...NO_CUSTOM_NODES_PRESET
                 }
                 }
             );
             );
 
 
             assert.match(
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
                 obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
+                /^var *test *= *'test';/
             );
             );
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
         });
         });
 
 
-        it('should create only one item in string array for same literal node values', () => {
-            let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
-                readFileAsString(__dirname + '/fixtures/same-literal-values.js'),
+        it('should\'t throw an error when string contains non-latin and non-digit characters and `unicodeEscapeSequence` is disabled', () => {
+            assert.doesNotThrow(() => JavaScriptObfuscator.obfuscate(
+                readFileAsString(__dirname + '/fixtures/error-when-non-latin.js'),
                 {
                 {
                     ...NO_CUSTOM_NODES_PRESET,
                     ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArray: true,
                     stringArrayThreshold: 1
                     stringArrayThreshold: 1
                 }
                 }
-            );
-
-            assert.match(
-                obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
-            );
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
+            ));
         });
         });
 
 
-        it('should replace literal node value with raw value from string array if `unicodeEscapeSequence` is disabled', () => {
+        it('should create only one item in string array for same literal node values', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
-                readFileAsString(__dirname + '/fixtures/simple-input.js'),
+                readFileAsString(__dirname + '/fixtures/same-literal-values.js'),
                 {
                 {
                     ...NO_CUSTOM_NODES_PRESET,
                     ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArray: true,
-                    stringArrayThreshold: 1,
-                    unicodeEscapeSequence: false
+                    stringArrayThreshold: 1
                 }
                 }
             );
             );
 
 
@@ -73,31 +69,35 @@ describe('LiteralTransformer', () => {
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
         });
         });
 
 
-        it('should replace literal node value with raw value from string array if `unicodeEscapeSequence` and `stringArray` are disabled', () => {
+        it('should replace literal node value with unicode escape sequence if `unicodeEscapeSequence` is enabled', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 {
                 {
                     ...NO_CUSTOM_NODES_PRESET,
                     ...NO_CUSTOM_NODES_PRESET,
-                    unicodeEscapeSequence: false
+                    unicodeEscapeSequence: true
+
                 }
                 }
             );
             );
 
 
-            assert.match(
-                obfuscationResult.getObfuscatedCode(),
-                /^var *test *= *'test';/
-            );
+            assert.match(obfuscationResult.getObfuscatedCode(),  /^var *test *= *'\\x74\\x65\\x73\\x74';$/);
         });
         });
 
 
-        it('should\'t throw an error when string contains non-latin and non-digit characters and `unicodeEscapeSequence` is disabled', () => {
-            assert.doesNotThrow(() => JavaScriptObfuscator.obfuscate(
-                readFileAsString(__dirname + '/fixtures/error-when-non-latin.js'),
+        it('should replace literal node value with unicode escape sequence from string array if `unicodeEscapeSequence` is enabled', () => {
+            let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(__dirname + '/fixtures/simple-input.js'),
                 {
                 {
                     ...NO_CUSTOM_NODES_PRESET,
                     ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArray: true,
                     stringArrayThreshold: 1,
                     stringArrayThreshold: 1,
-                    unicodeEscapeSequence: false
+                    unicodeEscapeSequence: true
                 }
                 }
-            ));
+            );
+
+            assert.match(
+                obfuscationResult.getObfuscatedCode(),
+                /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
+            );
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
         });
         });
 
 
         it('shouldn\'t replace short literal node value with value from string array', () => {
         it('shouldn\'t replace short literal node value with value from string array', () => {
@@ -110,7 +110,7 @@ describe('LiteralTransformer', () => {
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *'\\x74\\x65';/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *'te';/);
         });
         });
 
 
         it('should replace literal node value with value from string array encoded using base64', () => {
         it('should replace literal node value with value from string array encoded using base64', () => {
@@ -126,7 +126,7 @@ describe('LiteralTransformer', () => {
 
 
             assert.match(
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
                 obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-f0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/
+                /^var *_0x([a-f0-9]){4} *= *\['dGVzdA\\x3d\\x3d'\];/
             );
             );
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
         });
         });
@@ -144,7 +144,7 @@ describe('LiteralTransformer', () => {
 
 
             assert.match(
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
                 obfuscationResult.getObfuscatedCode(),
-                /var *test *= *_0x([a-f0-9]){4}\('0x0', '(\\x[a-f0-9]*){4}'\);/
+                /var *test *= *_0x([a-f0-9]){4}\('0x0', '(?:\w|(?:\\x[a-f0-9]*)){4}'\);/
             );
             );
         });
         });
 
 
@@ -162,7 +162,7 @@ describe('LiteralTransformer', () => {
             );
             );
 
 
             const regExp1: RegExp = /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/g;
             const regExp1: RegExp = /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/g;
-            const regExp2: RegExp = /var *test *= *'\\x74\\x65\\x73\\x74';/g;
+            const regExp2: RegExp = /var *test *= *'test';/g;
             const stringArrayMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
             const stringArrayMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
             const noStringArrayMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;
             const noStringArrayMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;
 
 

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

@@ -9,18 +9,7 @@ import { readFileAsString } from '../../../../helpers/readFileAsString';
 import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscator';
 import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscator';
 
 
 describe('ObjectExpressionTransformer', () => {
 describe('ObjectExpressionTransformer', () => {
-    it('should replace object expression node `key` property with literal value by unicode value', () => {
-        let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
-            readFileAsString(__dirname + '/fixtures/property-with-literal-value.js'),
-            {
-                ...NO_CUSTOM_NODES_PRESET
-            }
-        );
-
-        assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
-    });
-
-    it('should replace object expression node `key` property with identifier value by unicode value', () => {
+    it('should replace object expression node `key` property with identifier value by property with literal value', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             readFileAsString(__dirname + '/fixtures/property-with-identifier-value.js'),
             readFileAsString(__dirname + '/fixtures/property-with-identifier-value.js'),
             {
             {
@@ -28,7 +17,7 @@ describe('ObjectExpressionTransformer', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *\{'foo':0x0\};/);
     });
     });
 
 
     it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
     it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
@@ -41,7 +30,7 @@ describe('ObjectExpressionTransformer', () => {
 
 
         assert.match(
         assert.match(
             obfuscationResult.getObfuscatedCode(),
             obfuscationResult.getObfuscatedCode(),
-            /var *_0x[a-f0-9]{4,6} *= *\{'\\x61': *_0x[a-f0-9]{4,6}\, *'\\x62': *_0x[a-f0-9]{4,6}\};/
+            /var *_0x[a-f0-9]{4,6} *= *\{'a': *_0x[a-f0-9]{4,6}\, *'b': *_0x[a-f0-9]{4,6}\};/
         );
         );
     });
     });
 });
 });

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

@@ -17,8 +17,8 @@ describe('VariableDeclarationTransformer', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4,6} *= *'\\x61\\x62\\x63';/);
-        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-f0-9]){4,6}\);/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4,6} *= *'abc';/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['log'\]\(_0x([a-f0-9]){4,6}\);/);
     });
     });
 
 
     it('should not transform `variableDeclaration` node if parent block scope node is `Program` node', () => {
     it('should not transform `variableDeclaration` node if parent block scope node is `Program` node', () => {
@@ -30,7 +30,7 @@ describe('VariableDeclarationTransformer', () => {
         );
         );
 
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *0xa;/);
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *0xa;/);
-        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(test\);/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['log'\]\(test\);/);
     });
     });
 
 
     it('should transform variable call (`identifier` node) outside of block scope of node in which this variable was declared with `var` kind', () => {
     it('should transform variable call (`identifier` node) outside of block scope of node in which this variable was declared with `var` kind', () => {
@@ -41,7 +41,7 @@ describe('VariableDeclarationTransformer', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-f0-9]){4,6}\);/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['log'\]\(_0x([a-f0-9]){4,6}\);/);
     });
     });
 
 
     it('should not transform variable call (`identifier` node) outside of block scope of node in which this variable was declared with `let` kind', () => {
     it('should not transform variable call (`identifier` node) outside of block scope of node in which this variable was declared with `let` kind', () => {
@@ -52,7 +52,7 @@ describe('VariableDeclarationTransformer', () => {
             }
             }
         );
         );
 
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(test\);/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['log'\]\(test\);/);
     });
     });
 
 
     describe(`variable calls before variable declaration`, () => {
     describe(`variable calls before variable declaration`, () => {
@@ -68,11 +68,11 @@ describe('VariableDeclarationTransformer', () => {
         });
         });
 
 
         it('should transform variable call (`identifier` node name) before variable declaration if this call is inside function body', () => {
         it('should transform variable call (`identifier` node name) before variable declaration if this call is inside function body', () => {
-            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-f0-9]){4,6}\['\\x69\\x74\\x65\\x6d'\]\);/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['log'\]\(_0x([a-f0-9]){4,6}\['item'\]\);/);
         });
         });
 
 
         it('should transform variable call (`identifier` node name) before variable declaration', () => {
         it('should transform variable call (`identifier` node name) before variable declaration', () => {
-            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-f0-9]){4,6}\);/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['log'\]\(_0x([a-f0-9]){4,6}\);/);
         });
         });
     });
     });
 
 
@@ -90,9 +90,9 @@ describe('VariableDeclarationTransformer', () => {
         const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
             .match(/function _0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\) *\{/);
             .match(/function _0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\) *\{/);
         const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-            .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-f0-9]{4,6})\)/);
+            .match(/console\['log'\]\((_0x[a-f0-9]{4,6})\)/);
         const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-            .match(/return\{'\\x74':(_0x[a-f0-9]{4,6})\}/);
+            .match(/return\{'t':(_0x[a-f0-9]{4,6})\}/);
         const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
             .match(/var *(_0x[a-f0-9]{4,6});/);
             .match(/var *(_0x[a-f0-9]{4,6});/);
 
 
@@ -135,9 +135,9 @@ describe('VariableDeclarationTransformer', () => {
         const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
             .match(/function _0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\) *\{/);
             .match(/function _0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\) *\{/);
         const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-            .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-f0-9]{4,6})\)/);
+            .match(/console\['log'\]\((_0x[a-f0-9]{4,6})\)/);
         const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-            .match(/return\{'\\x74':(_0x[a-f0-9]{4,6})\}/);
+            .match(/return\{'t':(_0x[a-f0-9]{4,6})\}/);
         const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
         const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
             .match(/var *(_0x[a-f0-9]{4,6});/);
             .match(/var *(_0x[a-f0-9]{4,6});/);
 
 
@@ -175,7 +175,7 @@ describe('VariableDeclarationTransformer', () => {
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var _0x([a-f0-9]){4,6} *= *\{'\\x74\\x65\\x73\\x74/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var _0x([a-f0-9]){4,6} *= *\{'test/);
         });
         });
 
 
         it('shouldn\'t replace computed member expression identifier', () => {
         it('shouldn\'t replace computed member expression identifier', () => {
@@ -186,7 +186,7 @@ describe('VariableDeclarationTransformer', () => {
                 }
                 }
             );
             );
 
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /_0x([a-f0-9]){4,6}\['\\x74\\x65\\x73\\x74'\]/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /_0x([a-f0-9]){4,6}\['test'\]/);
         });
         });
     });
     });
 
 
@@ -200,8 +200,8 @@ describe('VariableDeclarationTransformer', () => {
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
         it('shouldn\'t transform object pattern variable declarator', () => {
         it('shouldn\'t transform object pattern variable declarator', () => {
-            const objectPatternVariableDeclaratorMatch: RegExp = /var *\{ *bar *\} *= *\{ *'\\x62\\x61\\x72' *: *'\\x66\\x6f\\x6f' *\};/;
-            const variableUsageMatch: RegExp = /console\['\\x6c\\x6f\\x67'\]\(bar\);/;
+            const objectPatternVariableDeclaratorMatch: RegExp = /var *\{ *bar *\} *= *\{ *'bar' *: *'foo' *\};/;
+            const variableUsageMatch: RegExp = /console\['log'\]\(bar\);/;
 
 
             assert.match(obfuscatedCode, objectPatternVariableDeclaratorMatch);
             assert.match(obfuscatedCode, objectPatternVariableDeclaratorMatch);
             assert.match(obfuscatedCode, variableUsageMatch);
             assert.match(obfuscatedCode, variableUsageMatch);
@@ -218,7 +218,7 @@ describe('VariableDeclarationTransformer', () => {
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
 
         const objectPatternVariableDeclaratorMatch: RegExp = /var *\[ *(_0x([a-f0-9]){4,6}), *(_0x([a-f0-9]){4,6}) *\] *= *\[0x1, *0x2\];/;
         const objectPatternVariableDeclaratorMatch: RegExp = /var *\[ *(_0x([a-f0-9]){4,6}), *(_0x([a-f0-9]){4,6}) *\] *= *\[0x1, *0x2\];/;
-        const variableUsageMatch: RegExp = /console\['\\x6c\\x6f\\x67'\]\((_0x([a-f0-9]){4,6}), *(_0x([a-f0-9]){4,6})\);/;
+        const variableUsageMatch: RegExp = /console\['log'\]\((_0x([a-f0-9]){4,6}), *(_0x([a-f0-9]){4,6})\);/;
 
 
         const objectPatternIdentifierName1: string = obfuscatedCode.match(objectPatternVariableDeclaratorMatch)![1];
         const objectPatternIdentifierName1: string = obfuscatedCode.match(objectPatternVariableDeclaratorMatch)![1];
         const objectPatternIdentifierName2: string = obfuscatedCode.match(objectPatternVariableDeclaratorMatch)![2];
         const objectPatternIdentifierName2: string = obfuscatedCode.match(objectPatternVariableDeclaratorMatch)![2];

+ 1 - 0
test/index.spec.ts

@@ -35,6 +35,7 @@ import './functional-tests/node-transformers/control-flow-transformers/function-
 import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec';
+import './functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/string-litertal-control-flow-replacer/StringLiteralControlFlowReplacer.spec';
 import './functional-tests/node-transformers/converting-transformers/member-expression-transformer/MemberExpressionTransformer.spec';
 import './functional-tests/node-transformers/converting-transformers/member-expression-transformer/MemberExpressionTransformer.spec';
 import './functional-tests/node-transformers/converting-transformers/method-definition-transformer/MethodDefinitionTransformer.spec';
 import './functional-tests/node-transformers/converting-transformers/method-definition-transformer/MethodDefinitionTransformer.spec';
 import './functional-tests/node-transformers/converting-transformers/template-literal-transformer/TemplateLiteralTransformer.spec';
 import './functional-tests/node-transformers/converting-transformers/template-literal-transformer/TemplateLiteralTransformer.spec';

+ 1 - 1
webpack.config.js

@@ -49,7 +49,7 @@ module.exports = {
         new CheckerPlugin()
         new CheckerPlugin()
     ],
     ],
     output: {
     output: {
-        path: './dist',
+        path: __dirname + '/dist',
         filename: '[name].js',
         filename: '[name].js',
         libraryTarget:  "commonjs2",
         libraryTarget:  "commonjs2",
         library: "JavaScriptObfuscator"
         library: "JavaScriptObfuscator"

+ 150 - 123
yarn.lock

@@ -1,7 +1,5 @@
 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 # yarn lockfile v1
 # yarn lockfile v1
-
-
 "@types/[email protected]":
 "@types/[email protected]":
   version "3.4.35"
   version "3.4.35"
   resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.35.tgz#e8d65f83492d2944f816fc620741821c28a8c900"
   resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.35.tgz#e8d65f83492d2944f816fc620741821c28a8c900"
@@ -44,13 +42,17 @@
   version "2.2.40"
   version "2.2.40"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.40.tgz#9811dd800ece544cd84b5b859917bf584a150c4c"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.40.tgz#9811dd800ece544cd84b5b859917bf584a150c4c"
 
 
-"@types/node@*", "@types/[email protected]":
-  version "7.0.8"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.8.tgz#25e4dd804b630c916ae671233e6d71f6ce18124a"
+"@types/node@*":
+  version "7.0.5"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.5.tgz#96a0f0a618b7b606f1ec547403c00650210bfbb7"
 
 
-"@types/[email protected]":
-  version "1.16.35"
-  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-1.16.35.tgz#ee687cc42d1a79448256f1c012a33a0840e85c5c"
+"@types/[email protected]":
+  version "7.0.10"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.10.tgz#d860abb18c1b58b552c7c6cd8b2ba7adf6546fa3"
+
+"@types/[email protected]":
+  version "1.16.36"
+  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-1.16.36.tgz#74bb6ed7928597c1b3fb1b009005e94dc6eae357"
 
 
 "@types/[email protected]":
 "@types/[email protected]":
   version "1.0.2"
   version "1.0.2"
@@ -107,10 +109,6 @@ ansi-styles@^2.2.1:
   version "2.2.1"
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
 
 
-any-promise@^1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
-
 anymatch@^1.3.0:
 anymatch@^1.3.0:
   version "1.3.0"
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@@ -193,7 +191,7 @@ async-each@^1.0.0:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
 
 
-[email protected], async@^1.4.0, async@^1.4.2:
+async@^1.4.0, async@^1.4.2, [email protected]:
   version "1.5.2"
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
   resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
 
 
@@ -284,7 +282,20 @@ babel-core@^6.24.0:
     slash "^1.0.0"
     slash "^1.0.0"
     source-map "^0.5.0"
     source-map "^0.5.0"
 
 
-babel-generator@^6.18.0, babel-generator@^6.24.0:
+babel-generator@^6.18.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.23.0.tgz#6b8edab956ef3116f79d8c84c5a3c05f32a74bc5"
+  dependencies:
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-types "^6.23.0"
+    detect-indent "^4.0.0"
+    jsesc "^1.3.0"
+    lodash "^4.2.0"
+    source-map "^0.5.0"
+    trim-right "^1.0.1"
+
+babel-generator@^6.24.0:
   version "6.24.0"
   version "6.24.0"
   resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.0.tgz#eba270a8cc4ce6e09a61be43465d7c62c1f87c56"
   resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.0.tgz#eba270a8cc4ce6e09a61be43465d7c62c1f87c56"
   dependencies:
   dependencies:
@@ -896,11 +907,11 @@ cipher-base@^1.0.0, cipher-base@^1.0.1:
   dependencies:
   dependencies:
     inherits "^2.0.1"
     inherits "^2.0.1"
 
 
-class-validator@0.6.8:
-  version "0.6.8"
-  resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.6.8.tgz#af34fa10f99ecb86679d291d73ef8076d9ab8b95"
+class-validator@0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.7.0.tgz#a45b96aaa2154d06efda1cac1061b0adf69ea55e"
   dependencies:
   dependencies:
-    validator ">=5.0.0"
+    validator "^7.0.0"
 
 
 cli-boxes@^1.0.0:
 cli-boxes@^1.0.0:
   version "1.0.0"
   version "1.0.0"
@@ -940,7 +951,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
   dependencies:
   dependencies:
     delayed-stream "~1.0.0"
     delayed-stream "~1.0.0"
 
 
-[email protected], commander@^2.8.1, commander@^2.9.0:
+commander@^2.8.1, commander@^2.9.0, commander@2.9.0:
   version "2.9.0"
   version "2.9.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
   dependencies:
   dependencies:
@@ -1072,7 +1083,7 @@ date-now@^0.1.4:
   version "0.1.4"
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
   resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
 
 
-[email protected], debug@^2.1.1, debug@^2.2.0, debug@~2.2.0:
+debug@^2.1.1, debug@^2.2.0, debug@~2.2.0, debug@2.2.0:
   version "2.2.0"
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
   dependencies:
   dependencies:
@@ -1123,14 +1134,14 @@ detect-indent@^4.0.0:
   dependencies:
   dependencies:
     repeating "^2.0.0"
     repeating "^2.0.0"
 
 
[email protected]:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf"
-
 diff@^3.0.1, diff@^3.1.0:
 diff@^3.0.1, diff@^3.1.0:
   version "3.2.0"
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
 
 
[email protected]:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf"
+
 diffie-hellman@^5.0.0:
 diffie-hellman@^5.0.0:
   version "5.0.2"
   version "5.0.2"
   resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
   resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
@@ -1196,7 +1207,7 @@ error-ex@^1.2.0:
   dependencies:
   dependencies:
     is-arrayish "^0.2.1"
     is-arrayish "^0.2.1"
 
 
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
+escape-string-regexp@^1.0.2, [email protected]:
   version "1.0.5"
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
 
 
@@ -1211,22 +1222,22 @@ [email protected]:
   optionalDependencies:
   optionalDependencies:
     source-map "~0.2.0"
     source-map "~0.2.0"
 
 
[email protected], esprima@^3.1.1:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
-
 esprima@^2.6.0, esprima@^2.7.1:
 esprima@^2.6.0, esprima@^2.7.1:
   version "2.7.3"
   version "2.7.3"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
 
 
-es[email protected]:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+esprima@^3.1.1, [email protected]:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
 
 
 estraverse@^1.9.1:
 estraverse@^1.9.1:
   version "1.9.3"
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
 
 
[email protected]:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
 esutils@^2.0.2:
 esutils@^2.0.2:
   version "2.0.2"
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
@@ -1438,17 +1449,6 @@ glob-parent@^2.0.0:
   dependencies:
   dependencies:
     is-glob "^2.0.0"
     is-glob "^2.0.0"
 
 
[email protected]:
-  version "7.0.5"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95"
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.2"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
 glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
 glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
   version "7.1.1"
   version "7.1.1"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
@@ -1470,6 +1470,17 @@ glob@~5.0.0:
     once "^1.3.0"
     once "^1.3.0"
     path-is-absolute "^1.0.0"
     path-is-absolute "^1.0.0"
 
 
[email protected]:
+  version "7.0.5"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95"
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.2"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
 globals@^9.0.0:
 globals@^9.0.0:
   version "9.16.0"
   version "9.16.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80"
@@ -1604,7 +1615,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     once "^1.3.0"
     wrappy "1"
     wrappy "1"
 
 
-inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1:
+inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@2:
   version "2.0.3"
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
 
 
@@ -1626,9 +1637,9 @@ invariant@^2.2.0:
   dependencies:
   dependencies:
     loose-envify "^1.0.0"
     loose-envify "^1.0.0"
 
 
-inversify@3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/inversify/-/inversify-3.1.0.tgz#820571ddf52e7d8f875a5de15de3468319b86f80"
+inversify@3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/inversify/-/inversify-3.3.0.tgz#57ca2e0aaac7b54aa5018ad69a10c5aba366e96e"
 
 
 invert-kv@^1.0.0:
 invert-kv@^1.0.0:
   version "1.0.0"
   version "1.0.0"
@@ -1749,14 +1760,14 @@ is-utf8@^0.2.0:
   version "0.2.1"
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
 
 
+isarray@^1.0.0, isarray@~1.0.0, [email protected]:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
 [email protected]:
 [email protected]:
   version "0.0.1"
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
 
 
[email protected], isarray@^1.0.0, isarray@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
-
 isexe@^1.1.1:
 isexe@^1.1.1:
   version "1.1.2"
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
@@ -1858,13 +1869,6 @@ js-tokens@^3.0.0:
   version "3.0.1"
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
 
 
[email protected], [email protected]:
-  version "3.6.1"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
-  dependencies:
-    argparse "^1.0.7"
-    esprima "^2.6.0"
-
 js-yaml@^3.7.0:
 js-yaml@^3.7.0:
   version "3.8.1"
   version "3.8.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
@@ -1872,6 +1876,13 @@ js-yaml@^3.7.0:
     argparse "^1.0.7"
     argparse "^1.0.7"
     esprima "^3.1.1"
     esprima "^3.1.1"
 
 
[email protected], [email protected]:
+  version "3.6.1"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^2.6.0"
+
 jsbn@~0.1.0:
 jsbn@~0.1.0:
   version "0.1.1"
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -2128,21 +2139,21 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
 
 
-"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3:
+minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, "minimatch@2 || 3":
   version "3.0.3"
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
   dependencies:
   dependencies:
     brace-expansion "^1.0.0"
     brace-expansion "^1.0.0"
 
 
[email protected], minimist@~0.0.1:
-  version "0.0.8"
-  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
-
[email protected], minimist@^1.2.0:
+minimist@^1.2.0, [email protected]:
   version "1.2.0"
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
 
 
[email protected], [email protected], "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
+minimist@~0.0.1, [email protected]:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+mkdirp@^0.5.0, mkdirp@^0.5.1, "mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1, [email protected], [email protected]:
   version "0.5.1"
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   dependencies:
   dependencies:
@@ -2218,7 +2229,7 @@ node-pre-gyp@^0.6.29:
     tar "~2.2.1"
     tar "~2.2.1"
     tar-pack "~3.3.0"
     tar-pack "~3.3.0"
 
 
-nopt@3.x, nopt@~3.0.6:
+nopt@~3.0.6, [email protected]:
   version "3.0.6"
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
   dependencies:
   dependencies:
@@ -2421,7 +2432,7 @@ pinkie-promise@^2.0.0:
   dependencies:
   dependencies:
     pinkie "^2.0.0"
     pinkie "^2.0.0"
 
 
-pinkie@^2.0.0, pinkie@^2.0.4:
+pinkie@^2.0.0:
   version "2.0.4"
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
 
 
@@ -2473,14 +2484,14 @@ public-encrypt@^4.0.0:
     parse-asn1 "^5.0.0"
     parse-asn1 "^5.0.0"
     randombytes "^2.0.1"
     randombytes "^2.0.1"
 
 
[email protected]:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
-
 punycode@^1.2.4, punycode@^1.4.1:
 punycode@^1.2.4, punycode@^1.4.1:
   version "1.4.1"
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
 
 
[email protected]:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+
 qs@~6.3.0:
 qs@~6.3.0:
   version "6.3.1"
   version "6.3.1"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.1.tgz#918c0b3bcd36679772baf135b1acb4c1651ed79d"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.1.tgz#918c0b3bcd36679772baf135b1acb4c1651ed79d"
@@ -2632,7 +2643,7 @@ repeating@^2.0.0:
   dependencies:
   dependencies:
     is-finite "^1.0.0"
     is-finite "^1.0.0"
 
 
[email protected], request@^2.79.0:
+request@^2.79.0, [email protected]:
   version "2.79.0"
   version "2.79.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
   resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
   dependencies:
   dependencies:
@@ -2677,7 +2688,7 @@ right-align@^0.1.1:
   dependencies:
   dependencies:
     align-text "^0.1.1"
     align-text "^0.1.1"
 
 
-rimraf@2, rimraf@^2.4.3, rimraf@^2.4.4:
+rimraf@^2.4.3, rimraf@^2.4.4, rimraf@2:
   version "2.6.1"
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
   dependencies:
   dependencies:
@@ -2697,7 +2708,7 @@ safe-buffer@^5.0.1:
   version "5.0.1"
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
 
 
-samsam@1.x, samsam@^1.1.3:
+samsam@^1.1.3, [email protected]:
   version "1.2.1"
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67"
   resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67"
 
 
@@ -2707,7 +2718,7 @@ semver-diff@^2.0.0:
   dependencies:
   dependencies:
     semver "^5.0.3"
     semver "^5.0.3"
 
 
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0:
+semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0, "semver@2 || 3 || 4 || 5":
   version "5.3.0"
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
 
 
@@ -2733,9 +2744,9 @@ signal-exit@^3.0.0:
   version "3.0.2"
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
 
-sinon@2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.0.0.tgz#48337fa489069e530ad7e2f44f07b0ae93d37b24"
+sinon@2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.1.0.tgz#e057a9d2bf1b32f5d6dd62628ca9ee3961b0cafb"
   dependencies:
   dependencies:
     diff "^3.1.0"
     diff "^3.1.0"
     formatio "1.2.0"
     formatio "1.2.0"
@@ -2760,13 +2771,19 @@ [email protected]:
   dependencies:
   dependencies:
     hoek "2.x.x"
     hoek "2.x.x"
 
 
-source-list-map@~0.1.7:
-  version "0.1.8"
-  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
+source-list-map@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.0.1.tgz#cc1fc17122ae0a51978024c2cc0f8c35659026b8"
+
+source-map-support@^0.4.0, source-map-support@^0.4.11, source-map-support@^0.4.2:
+  version "0.4.11"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.11.tgz#647f939978b38535909530885303daf23279f322"
+  dependencies:
+    source-map "^0.5.3"
 
 
[email protected], source-map-support@^0.4.0, source-map-support@^0.4.11, source-map-support@^0.4.2:
-  version "0.4.13"
-  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.13.tgz#9782e6f7deb424d5f173327a1879eb46453bdcd4"
[email protected]:
+  version "0.4.14"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.14.tgz#9d4463772598b86271b4f523f6c1f4e02a7d6aef"
   dependencies:
   dependencies:
     source-map "^0.5.6"
     source-map "^0.5.6"
 
 
@@ -2836,6 +2853,10 @@ stream-http@^2.3.1:
     to-arraybuffer "^1.0.0"
     to-arraybuffer "^1.0.0"
     xtend "^4.0.0"
     xtend "^4.0.0"
 
 
+string_decoder@^0.10.25, string_decoder@~0.10.x:
+  version "0.10.31"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
 [email protected]:
 [email protected]:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96"
   resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96"
@@ -2855,10 +2876,6 @@ string-width@^2.0.0:
     is-fullwidth-code-point "^2.0.0"
     is-fullwidth-code-point "^2.0.0"
     strip-ansi "^3.0.0"
     strip-ansi "^3.0.0"
 
 
-string_decoder@^0.10.25, string_decoder@~0.10.x:
-  version "0.10.31"
-  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
-
 stringstream@~0.0.4:
 stringstream@~0.0.4:
   version "0.0.5"
   version "0.0.5"
   resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
   resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@@ -2875,6 +2892,10 @@ strip-bom@^2.0.0:
   dependencies:
   dependencies:
     is-utf8 "^0.2.0"
     is-utf8 "^0.2.0"
 
 
+strip-bom@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+
 strip-eof@^1.0.0:
 strip-eof@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -2883,16 +2904,16 @@ strip-json-comments@^2.0.0, strip-json-comments@~2.0.1:
   version "2.0.1"
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
 
 
[email protected], supports-color@^3.1.0, supports-color@^3.1.2:
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.0, supports-color@^3.1.2, [email protected]:
   version "3.1.2"
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
   dependencies:
   dependencies:
     has-flag "^1.0.0"
     has-flag "^1.0.0"
 
 
-supports-color@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
-
 tapable@^0.2.5, tapable@~0.2.5:
 tapable@^0.2.5, tapable@~0.2.5:
   version "0.2.6"
   version "0.2.6"
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d"
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d"
@@ -2956,9 +2977,9 @@ trim-right@^1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
   resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
 
 
-ts-node@2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-2.1.0.tgz#aa2bf4b2e25c5fb6a7c54701edc3666d3a9db25d"
+ts-node@3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-3.0.2.tgz#cfc9516c831b920d7efbe16005915062b1294f8c"
   dependencies:
   dependencies:
     arrify "^1.0.0"
     arrify "^1.0.0"
     chalk "^1.1.1"
     chalk "^1.1.1"
@@ -2966,20 +2987,16 @@ [email protected]:
     make-error "^1.1.1"
     make-error "^1.1.1"
     minimist "^1.2.0"
     minimist "^1.2.0"
     mkdirp "^0.5.1"
     mkdirp "^0.5.1"
-    pinkie "^2.0.4"
     source-map-support "^0.4.0"
     source-map-support "^0.4.0"
-    tsconfig "^5.0.2"
+    tsconfig "^6.0.0"
     v8flags "^2.0.11"
     v8flags "^2.0.11"
-    xtend "^4.0.0"
     yn "^1.2.0"
     yn "^1.2.0"
 
 
-tsconfig@^5.0.2:
-  version "5.0.3"
-  resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-5.0.3.tgz#5f4278e701800967a8fc383fd19648878f2a6e3a"
+tsconfig@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-6.0.0.tgz#6b0e8376003d7af1864f8df8f89dd0059ffcd032"
   dependencies:
   dependencies:
-    any-promise "^1.3.0"
-    parse-json "^2.2.0"
-    strip-bom "^2.0.0"
+    strip-bom "^3.0.0"
     strip-json-comments "^2.0.0"
     strip-json-comments "^2.0.0"
 
 
 [email protected]:
 [email protected]:
@@ -3044,7 +3061,7 @@ [email protected]:
   version "2.2.0"
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.0.tgz#626f2fc70087d2480f21ebb12c1888288c8614e3"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.0.tgz#626f2fc70087d2480f21ebb12c1888288c8614e3"
 
 
-uglify-js@^2.6, uglify-js@^2.7.5:
+uglify-js@^2.6:
   version "2.8.4"
   version "2.8.4"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.4.tgz#5aeb6fd6f1f0a672dea63795016590502c290513"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.4.tgz#5aeb6fd6f1f0a672dea63795016590502c290513"
   dependencies:
   dependencies:
@@ -3053,6 +3070,15 @@ uglify-js@^2.6, uglify-js@^2.7.5:
     uglify-to-browserify "~1.0.0"
     uglify-to-browserify "~1.0.0"
     yargs "~3.10.0"
     yargs "~3.10.0"
 
 
+uglify-js@^2.8.5:
+  version "2.8.15"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.15.tgz#835dd4cd5872554756e6874508d0d0561704d94d"
+  dependencies:
+    source-map "~0.5.1"
+    yargs "~3.10.0"
+  optionalDependencies:
+    uglify-to-browserify "~1.0.0"
+
 uglify-to-browserify@~1.0.0:
 uglify-to-browserify@~1.0.0:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
   resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
@@ -3105,7 +3131,7 @@ util-deprecate@~1.0.1:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
 
 
[email protected], util@^0.10.3:
+util@^0.10.3, [email protected]:
   version "0.10.3"
   version "0.10.3"
   resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
   resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
   dependencies:
   dependencies:
@@ -3128,7 +3154,7 @@ validate-npm-package-license@^3.0.1:
     spdx-correct "~1.0.0"
     spdx-correct "~1.0.0"
     spdx-expression-parse "~1.0.0"
     spdx-expression-parse "~1.0.0"
 
 
-validator@>=5.0.0:
+validator@^7.0.0:
   version "7.0.0"
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/validator/-/validator-7.0.0.tgz#c74deb8063512fac35547938e6f0b1504a282fd2"
   resolved "https://registry.yarnpkg.com/validator/-/validator-7.0.0.tgz#c74deb8063512fac35547938e6f0b1504a282fd2"
 
 
@@ -3144,7 +3170,7 @@ [email protected]:
   dependencies:
   dependencies:
     indexof "0.0.1"
     indexof "0.0.1"
 
 
-watchpack@^1.2.0:
+watchpack@^1.3.1:
   version "1.3.1"
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87"
   dependencies:
   dependencies:
@@ -3156,16 +3182,16 @@ [email protected]:
   version "1.5.4"
   version "1.5.4"
   resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.5.4.tgz#ea05ba17108a23e776c35c42e7bb0e86c225be00"
   resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.5.4.tgz#ea05ba17108a23e776c35c42e7bb0e86c225be00"
 
 
-webpack-sources@^0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.4.tgz#ccc2c817e08e5fa393239412690bb481821393cd"
+webpack-sources@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.0.tgz#fea93ba840f16cdd3f246f0ee95f88a9492c69fb"
   dependencies:
   dependencies:
-    source-list-map "~0.1.7"
+    source-list-map "^1.0.1"
     source-map "~0.5.3"
     source-map "~0.5.3"
 
 
-webpack@2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.2.1.tgz#7bb1d72ae2087dd1a4af526afec15eed17dda475"
+webpack@2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.3.1.tgz#55bce8baffe7c1f9dc3029adc048643b448318a8"
   dependencies:
   dependencies:
     acorn "^4.0.4"
     acorn "^4.0.4"
     acorn-dynamic-import "^2.0.0"
     acorn-dynamic-import "^2.0.0"
@@ -3183,9 +3209,9 @@ [email protected]:
     source-map "^0.5.3"
     source-map "^0.5.3"
     supports-color "^3.1.0"
     supports-color "^3.1.0"
     tapable "~0.2.5"
     tapable "~0.2.5"
-    uglify-js "^2.7.5"
-    watchpack "^1.2.0"
-    webpack-sources "^0.1.4"
+    uglify-js "^2.8.5"
+    watchpack "^1.3.1"
+    webpack-sources "^0.2.0"
     yargs "^6.0.0"
     yargs "^6.0.0"
 
 
 which-module@^1.0.0:
 which-module@^1.0.0:
@@ -3214,10 +3240,6 @@ [email protected]:
   version "0.1.0"
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
   resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
 
 
[email protected]:
-  version "0.0.2"
-  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
-
 wordwrap@^1.0.0, wordwrap@~1.0.0:
 wordwrap@^1.0.0, wordwrap@~1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
@@ -3226,6 +3248,10 @@ wordwrap@~0.0.2:
   version "0.0.3"
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
 
 
[email protected]:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+
 wrap-ansi@^2.0.0:
 wrap-ansi@^2.0.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
@@ -3297,3 +3323,4 @@ yargs@~3.10.0:
 yn@^1.2.0:
 yn@^1.2.0:
   version "1.2.0"
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/yn/-/yn-1.2.0.tgz#d237a4c533f279b2b89d3acac2db4b8c795e4a63"
   resolved "https://registry.yarnpkg.com/yn/-/yn-1.2.0.tgz#d237a4c533f279b2b89d3acac2db4b8c795e4a63"
+

Some files were not shown because too many files changed in this diff