Ver Fonte

Merge branch 'dev'

# Conflicts:
#	package.json
sanex3339 há 8 anos atrás
pai
commit
2ee183d317
62 ficheiros alterados com 567 adições e 438 exclusões
  1. 12 0
      CHANGELOG.md
  2. 1 1
      README.md
  3. 201 215
      dist/index.js
  4. 17 17
      package.json
  5. 1 1
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  6. 1 1
      src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts
  7. 1 1
      src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts
  8. 1 1
      src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts
  9. 1 1
      src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts
  10. 1 1
      src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts
  11. 1 1
      src/custom-nodes/domain-lock-nodes/DomainLockNode.ts
  12. 1 1
      src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts
  13. 1 1
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  14. 1 1
      src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts
  15. 2 2
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  16. 1 1
      src/declarations/escodegen.d.ts
  17. 3 3
      src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts
  18. 10 7
      src/node-transformers/obfuscation-transformers/CatchClauseTransformer.ts
  19. 2 4
      src/node-transformers/obfuscation-transformers/FunctionDeclarationTransformer.ts
  20. 4 6
      src/node-transformers/obfuscation-transformers/FunctionTransformer.ts
  21. 2 6
      src/node-transformers/obfuscation-transformers/LabeledStatementTransformer.ts
  22. 1 1
      src/node-transformers/obfuscation-transformers/LiteralTransformer.ts
  23. 1 1
      src/node-transformers/obfuscation-transformers/MemberExpressionTransformer.ts
  24. 1 1
      src/node-transformers/obfuscation-transformers/MethodDefinitionTransformer.ts
  25. 1 1
      src/node-transformers/obfuscation-transformers/ObjectExpressionTransformer.ts
  26. 1 1
      src/node-transformers/obfuscation-transformers/TemplateLiteralTransformer.ts
  27. 4 4
      src/node-transformers/obfuscation-transformers/VariableDeclarationTransformer.ts
  28. 1 1
      src/node-transformers/obfuscation-transformers/replacers/IdentifierReplacer.ts
  29. 2 20
      src/node/Node.ts
  30. 19 18
      src/node/NodeUtils.ts
  31. 3 3
      src/stack-trace-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor.ts
  32. 3 3
      src/stack-trace-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor.ts
  33. 3 3
      src/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts
  34. 1 1
      src/storages/string-array/StringArrayStorage.ts
  35. 23 4
      src/templates/custom-nodes/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate.ts
  36. 1 1
      src/utils/CryptUtils.ts
  37. 9 6
      src/utils/RandomGeneratorUtils.ts
  38. 1 1
      test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts
  39. 2 2
      test/functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec.ts
  40. 1 1
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayCallsWrapper.spec.ts
  41. 2 2
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayNode.spec.ts
  42. 2 2
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.spec.ts
  43. 8 8
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts
  44. 3 3
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/binary-expression-control-flow-replacer/BinaryExpressionControlFlowReplacer.spec.ts
  45. 4 4
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/CallExpressionControlFlowReplacer.spec.ts
  46. 5 5
      test/functional-tests/node-transformers/control-flow-transformers/control-flow-replacers/logical-expression-control-flow-replacer/LogicalExpressionControlFlowReplacer.spec.ts
  47. 2 2
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts
  48. 20 2
      test/functional-tests/node-transformers/obfuscation-transformers/catch-clause-transformer/CatchClauseTransformer.spec.ts
  49. 7 0
      test/functional-tests/node-transformers/obfuscation-transformers/catch-clause-transformer/fixtures/object-pattern-as-parameter.js
  50. 2 2
      test/functional-tests/node-transformers/obfuscation-transformers/function-declaration-transformer/FunctionDeclarationTransformer.spec.ts
  51. 20 2
      test/functional-tests/node-transformers/obfuscation-transformers/function-transformer/FunctionTransformer.spec.ts
  52. 5 0
      test/functional-tests/node-transformers/obfuscation-transformers/function-transformer/fixtures/object-pattern-as-parameter.js
  53. 3 3
      test/functional-tests/node-transformers/obfuscation-transformers/labeled-statement-transformer/LabeledStatementTransformer.spec.ts
  54. 10 10
      test/functional-tests/node-transformers/obfuscation-transformers/literal-transformer/LiteralTransformer.spec.ts
  55. 4 4
      test/functional-tests/node-transformers/obfuscation-transformers/member-expression-transformer/MemberExpressionTransformer.spec.ts
  56. 2 2
      test/functional-tests/node-transformers/obfuscation-transformers/method-definition-transformer/MethodDefinitionTransformer.spec.ts
  57. 1 1
      test/functional-tests/node-transformers/obfuscation-transformers/object-expression-transformer/ObjectExpressionTransformer.spec.ts
  58. 99 38
      test/functional-tests/node-transformers/obfuscation-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts
  59. 4 0
      test/functional-tests/node-transformers/obfuscation-transformers/variable-declaration-transformer/fixtures/object-pattern.js
  60. 14 0
      test/functional-tests/node-transformers/obfuscation-transformers/variable-declaration-transformer/fixtures/variable-call-before-variable-declaration-3.js
  61. 2 2
      test/unit-tests/utils/random-generator-utils/RandomGeneratorUtils.spec.ts
  62. 5 1
      tslint.json

+ 12 - 0
CHANGELOG.md

@@ -1,5 +1,17 @@
 Change Log
 ===
+v0.8.6
+---
+* additional fixes for https://github.com/javascript-obfuscator/javascript-obfuscator/issues/29
+
+v0.8.5
+---
+* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/29
+
+v0.8.4
+---
+* fixed https://github.com/javascript-obfuscator/webpack-obfuscator/issues/13
+
 v0.8.3
 ---
 * `selfDefending` option now disabled by default.

+ 1 - 1
README.md

@@ -298,7 +298,7 @@ If checked, an interval is used to force the debug mode on the Console tab, maki
 ### `disableConsoleOutput`
 Type: `boolean` Default: `true`
 
-Disables the use of `console.log`, `console.info`, `console.error` and `console.warn` by replacing them with empty functions. This makes the use of the debugger harder.
+Disables the use of `console.log`, `console.info`, `console.error`, `console.warn`, `console.debug`, `console.exception` and `console.trace` by replacing them with empty functions. This makes the use of the debugger harder.
 
 ### `domainLock`
 Type: `string[]` Default: `[]`

Diff do ficheiro suprimidas por serem muito extensas
+ 201 - 215
dist/index.js


+ 17 - 17
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.9.0-dev.9",
+  "version": "0.9.0-dev.10",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -20,21 +20,21 @@
     "javascript-obfuscator": "./bin/javascript-obfuscator.js"
   },
   "dependencies": {
-    "babel-polyfill": "^6.20.0",
-    "babel-runtime": "^6.20.0",
+    "babel-polyfill": "6.20.0",
+    "babel-runtime": "6.20.0",
     "chance": "1.0.4",
-    "class-validator": "0.6.6",
+    "class-validator": "0.6.8",
     "commander": "2.9.0",
     "escodegen": "1.8.1",
     "esprima": "3.1.3",
     "estraverse": "4.2.0",
-    "inversify": "^3.0.0-rc.4",
-    "lodash": "^4.17.4",
+    "inversify": "3.0.0-rc.4",
+    "lodash": "4.17.4",
     "mkdirp": "0.5.1",
-    "reflect-metadata": "^0.1.9",
+    "reflect-metadata": "0.1.9",
     "source-map-support": "0.4.8",
-    "string-template": "^1.0.0",
-    "tslib": "^1.5.0"
+    "string-template": "1.0.0",
+    "tslib": "1.5.0"
   },
   "devDependencies": {
     "@types/chai": "3.4.34",
@@ -44,16 +44,16 @@
     "@types/esprima": "2.1.33",
     "@types/estraverse": "0.0.6",
     "@types/estree": "0.0.34",
-    "@types/lodash": "^4.14.45",
+    "@types/lodash": "4.14.48",
     "@types/mkdirp": "0.3.29",
-    "@types/mocha": "2.2.35",
-    "@types/node": "6.0.57",
+    "@types/mocha": "2.2.37",
+    "@types/node": "6.0.59",
     "@types/sinon": "1.16.34",
     "@types/string-template": "1.0.2",
-    "awesome-typescript-loader": "3.0.0-beta.17",
+    "awesome-typescript-loader": "3.0.0-beta.18",
     "babel-cli": "6.18.0",
     "babel-loader": "6.2.10",
-    "babel-plugin-transform-runtime": "^6.15.0",
+    "babel-plugin-transform-runtime": "6.15.0",
     "babel-preset-es2015": "6.18.0",
     "chai": "4.0.0-canary.1",
     "coveralls": "2.11.15",
@@ -61,10 +61,10 @@
     "mocha": "3.2.0",
     "sinon": "2.0.0-pre.4",
     "ts-node": "2.0.0",
-    "tslint": "4.2.0",
-    "tslint-loader": "^3.3.0",
+    "tslint": "4.3.1",
+    "tslint-loader": "3.3.0",
     "typescript": "2.1.4",
-    "webpack": "2.2.0-rc.2",
+    "webpack": "2.2.0-rc.3",
     "webpack-node-externals": "1.5.4"
   },
   "repository": {

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

@@ -51,7 +51,7 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
      */
     protected getTemplate (): string {
         return format(ConsoleOutputDisableExpressionTemplate(), {
-            consoleLogDisableFunctionName: RandomGeneratorUtils.getRandomVariableName(6, true, true),
+            consoleLogDisableFunctionName: RandomGeneratorUtils.getRandomVariableName(6),
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
     }

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

@@ -96,7 +96,7 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
+        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
 
         const consoleOutputDisableExpressionNode: ICustomNode = this.customNodeFactory(CustomNodes.ConsoleOutputDisableExpressionNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

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

@@ -43,7 +43,7 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
      */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = Nodes.getFunctionDeclarationNode(
-            RandomGeneratorUtils.getRandomVariableName(1, true, false),
+            RandomGeneratorUtils.getRandomString(3),
             [
                 Nodes.getIdentifierNode('x'),
                 Nodes.getIdentifierNode('y')

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

@@ -51,7 +51,7 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
         }
 
         const structure: TStatement = Nodes.getFunctionDeclarationNode(
-            RandomGeneratorUtils.getRandomVariableName(1, true, false),
+            RandomGeneratorUtils.getRandomString(3),
             [
                 calleeIdentifier,
                 ...params

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

@@ -43,7 +43,7 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
      */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = Nodes.getFunctionDeclarationNode(
-            RandomGeneratorUtils.getRandomVariableName(1, true, false),
+            RandomGeneratorUtils.getRandomString(3),
             [
                 Nodes.getIdentifierNode('x'),
                 Nodes.getIdentifierNode('y')

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

@@ -89,7 +89,7 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const debugProtectionFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
+        const debugProtectionFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
 
         const debugProtectionFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.DebugProtectionFunctionNode);
         const debugProtectionFunctionCallNode: ICustomNode = this.customNodeFactory(CustomNodes.DebugProtectionFunctionCallNode);

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

@@ -55,7 +55,7 @@ export class DomainLockNode extends AbstractCustomNode {
         const [hiddenDomainsString, diff]: string[] = CryptUtils.hideString(domainsString, domainsString.length * 3);
 
         return format(DomainLockNodeTemplate(), {
-            domainLockFunctionName: RandomGeneratorUtils.getRandomVariableName(6, true, true),
+            domainLockFunctionName: RandomGeneratorUtils.getRandomVariableName(6),
             diff: diff,
             domains: hiddenDomainsString,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName

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

@@ -96,7 +96,7 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
+        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
 
         const domainLockNode: ICustomNode = this.customNodeFactory(CustomNodes.DomainLockNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

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

@@ -55,7 +55,7 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
     protected getTemplate (): string {
         return JavaScriptObfuscator.obfuscate(
             format(SelfDefendingTemplate(), {
-                selfDefendingFunctionName: RandomGeneratorUtils.getRandomVariableName(6, true, true),
+                selfDefendingFunctionName: RandomGeneratorUtils.getRandomVariableName(6),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
             {

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

@@ -96,7 +96,7 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
+        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
 
         const selfDefendingUnicodeNode: ICustomNode = this.customNodeFactory(CustomNodes.SelfDefendingUnicodeNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

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

@@ -76,8 +76,8 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
      * @returns {string}
      */
     protected getTemplate (): string {
-        const timesName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
-        const whileFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
+        const timesName: string = RandomGeneratorUtils.getRandomVariableName(6);
+        const whileFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
 
         let code: string = '';
 

+ 1 - 1
src/declarations/escodegen.d.ts

@@ -6,5 +6,5 @@ declare module 'escodegen' {
      * @param options
      * @returns IGeneratorOutput
      */
-    export function generate(ast: any, options?: GenerateOptions): IGeneratorOutput;
+    export function generate (ast: any, options?: GenerateOptions): IGeneratorOutput;
 }

+ 3 - 3
src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -62,14 +62,14 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
         }
 
         const blockStatementBody: ESTree.Statement[] = blockStatementNode.body;
-        const originalKeys: number[] = [...Array(blockStatementBody.length).keys()];
-        const shuffledKeys: number[] = Utils.arrayShuffle(originalKeys);
-        const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
 
         if (blockStatementBody.length <= 4) {
             return blockStatementNode;
         }
 
+        const originalKeys: number[] = [...Array(blockStatementBody.length).keys()];
+        const shuffledKeys: number[] = Utils.arrayShuffle(originalKeys);
+        const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
         const blockStatementControlFlowFlatteningCustomNode: ICustomNode = this.customNodeFactory(
             CustomNodes.BlockStatementControlFlowFlatteningNode
         );

+ 10 - 7
src/node-transformers/obfuscation-transformers/CatchClauseTransformer.ts

@@ -9,11 +9,9 @@ import { IObfuscationReplacer } from '../../interfaces/node-transformers/IObfusc
 import { IObfuscationReplacerWithStorage } from '../../interfaces/node-transformers/IObfuscationReplacerWithStorage';
 
 import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscationReplacers';
-import { NodeType } from '../../enums/NodeType';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
-import { NodeUtils } from '../../node/NodeUtils';
 
 /**
  * replaces:
@@ -34,7 +32,7 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
      * @param replacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
@@ -61,9 +59,9 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
      * @param nodeIdentifier
      */
     private storeCatchClauseParam (catchClauseNode: ESTree.CatchClause, nodeIdentifier: number): void {
-        NodeUtils.typedTraverse(catchClauseNode.param, NodeType.Identifier, {
-            enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name, nodeIdentifier)
-        });
+        if (Node.isIdentifierNode(catchClauseNode.param)) {
+            this.identifierReplacer.storeNames(catchClauseNode.param.name, nodeIdentifier);
+        }
     }
 
     /**
@@ -74,7 +72,12 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
         estraverse.replace(catchClauseNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (Node.isReplaceableIdentifierNode(node, parentNode)) {
-                    node.name = this.identifierReplacer.replace(node.name, nodeIdentifier);
+                    const newNodeName: string = this.identifierReplacer.replace(node.name, nodeIdentifier);
+
+                    if (node.name !== newNodeName) {
+                        node.name = newNodeName;
+                        node.obfuscated = true;
+                    }
                 }
             }
         });

+ 2 - 4
src/node-transformers/obfuscation-transformers/FunctionDeclarationTransformer.ts

@@ -42,7 +42,7 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
      * @param nodeObfuscatorsReplacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) nodeObfuscatorsReplacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
@@ -76,9 +76,7 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
      * @param nodeIdentifier
      */
     private storeFunctionName (functionDeclarationNode: ESTree.FunctionDeclaration, nodeIdentifier: number): void {
-        NodeUtils.typedTraverse(functionDeclarationNode.id, NodeType.Identifier, {
-            enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name, nodeIdentifier)
-        });
+        this.identifierReplacer.storeNames(functionDeclarationNode.id.name, nodeIdentifier);
     }
 
     /**

+ 4 - 6
src/node-transformers/obfuscation-transformers/FunctionTransformer.ts

@@ -9,11 +9,9 @@ import { IObfuscationReplacer } from '../../interfaces/node-transformers/IObfusc
 import { IObfuscationReplacerWithStorage } from '../../interfaces/node-transformers/IObfuscationReplacerWithStorage';
 
 import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscationReplacers';
-import { NodeType } from '../../enums/NodeType';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
-import { NodeUtils } from '../../node/NodeUtils';
 
 /**
  * replaces:
@@ -34,7 +32,7 @@ export class FunctionTransformer extends AbstractNodeTransformer {
      * @param nodeObfuscatorsReplacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) nodeObfuscatorsReplacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
@@ -63,9 +61,9 @@ export class FunctionTransformer extends AbstractNodeTransformer {
     private storeFunctionParams (functionNode: ESTree.Function, nodeIdentifier: number): void {
         functionNode.params
             .forEach((paramsNode: ESTree.Node) => {
-                NodeUtils.typedTraverse(paramsNode, NodeType.Identifier, {
-                    enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name, nodeIdentifier)
-                });
+                if (Node.isIdentifierNode(paramsNode)) {
+                    this.identifierReplacer.storeNames(paramsNode.name, nodeIdentifier);
+                }
             });
     }
 

+ 2 - 6
src/node-transformers/obfuscation-transformers/LabeledStatementTransformer.ts

@@ -9,11 +9,9 @@ import { IObfuscationReplacer } from '../../interfaces/node-transformers/IObfusc
 import { IObfuscationReplacerWithStorage } from '../../interfaces/node-transformers/IObfuscationReplacerWithStorage';
 
 import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscationReplacers';
-import { NodeType } from '../../enums/NodeType';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
-import { NodeUtils } from '../../node/NodeUtils';
 
 /**
  * replaces:
@@ -42,7 +40,7 @@ export class LabeledStatementTransformer extends AbstractNodeTransformer {
      * @param nodeObfuscatorsReplacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) nodeObfuscatorsReplacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
@@ -69,9 +67,7 @@ export class LabeledStatementTransformer extends AbstractNodeTransformer {
      * @param nodeIdentifier
      */
     private storeLabeledStatementName (labeledStatementNode: ESTree.LabeledStatement, nodeIdentifier: number): void {
-        NodeUtils.typedTraverse(labeledStatementNode.label, NodeType.Identifier, {
-            enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name, nodeIdentifier)
-        });
+        this.identifierReplacer.storeNames(labeledStatementNode.label.name, nodeIdentifier);
     }
 
     /**

+ 1 - 1
src/node-transformers/obfuscation-transformers/LiteralTransformer.ts

@@ -23,7 +23,7 @@ export class LiteralTransformer extends AbstractNodeTransformer {
      * @param replacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {

+ 1 - 1
src/node-transformers/obfuscation-transformers/MemberExpressionTransformer.ts

@@ -23,7 +23,7 @@ export class MemberExpressionTransformer extends AbstractNodeTransformer {
      * @param replacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {

+ 1 - 1
src/node-transformers/obfuscation-transformers/MethodDefinitionTransformer.ts

@@ -37,7 +37,7 @@ export class MethodDefinitionTransformer extends AbstractNodeTransformer {
      * @param replacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {

+ 1 - 1
src/node-transformers/obfuscation-transformers/ObjectExpressionTransformer.ts

@@ -27,7 +27,7 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
     /**
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);

+ 1 - 1
src/node-transformers/obfuscation-transformers/TemplateLiteralTransformer.ts

@@ -27,7 +27,7 @@ export class TemplateLiteralTransformer extends AbstractNodeTransformer {
      * @param replacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {

+ 4 - 4
src/node-transformers/obfuscation-transformers/VariableDeclarationTransformer.ts

@@ -43,7 +43,7 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
      * @param replacersFactory
      * @param options
      */
-    constructor(
+    constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
@@ -83,9 +83,9 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
     private storeVariableNames (variableDeclarationNode: ESTree.VariableDeclaration, nodeIdentifier: number): void {
         variableDeclarationNode.declarations
             .forEach((declarationNode: ESTree.VariableDeclarator) => {
-                NodeUtils.typedTraverse(declarationNode.id, NodeType.Identifier, {
-                    enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name, nodeIdentifier)
-                });
+                if (Node.isIdentifierNode(declarationNode.id)) {
+                    this.identifierReplacer.storeNames(declarationNode.id.name, nodeIdentifier);
+                }
             });
     }
 

+ 1 - 1
src/node-transformers/obfuscation-transformers/replacers/IdentifierReplacer.ts

@@ -47,7 +47,7 @@ export class IdentifierReplacer extends AbstractReplacer implements IObfuscation
      */
     public storeNames (nodeName: string, nodeIdentifier: number): void {
         if (!this.isReservedName(nodeName)) {
-            this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, RandomGeneratorUtils.getRandomVariableName(6, true, true));
+            this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, RandomGeneratorUtils.getRandomVariableName(6));
         }
     }
 

+ 2 - 20
src/node/Node.ts

@@ -1,24 +1,10 @@
 import * as ESTree from 'estree';
 
 import { TNodeWithBlockStatement } from '../types/node/TNodeWithBlockStatement';
-import { TStatement } from '../types/node/TStatement';
 
 import { NodeType } from '../enums/NodeType';
 
 export class Node {
-    /**
-     * @param bodyNode
-     * @returns ESTree.Program
-     */
-    public static getProgramNode (bodyNode: TStatement[]): ESTree.Program {
-        return {
-            'type': NodeType.Program,
-            'body': bodyNode,
-            'sourceType': 'script',
-            'obfuscated': false
-        };
-    }
-
     /**
      * @param node
      * @returns {boolean}
@@ -109,9 +95,7 @@ export class Node {
         const parentNodeIsContinueStatementNode: boolean = Node.isContinueStatementNode(parentNode) && parentNode.label === node;
         const parentNodeIsBreakStatementNode: boolean = Node.isBreakStatementNode(parentNode) && parentNode.label === node;
 
-        return parentNodeIsLabeledStatementNode ||
-            parentNodeIsContinueStatementNode ||
-            parentNodeIsBreakStatementNode;
+        return parentNodeIsLabeledStatementNode || parentNodeIsContinueStatementNode || parentNodeIsBreakStatementNode;
     }
 
     /**
@@ -181,9 +165,7 @@ export class Node {
             parentNode.property === node
         );
 
-        return !parentNodeIsPropertyNode &&
-            !parentNodeIsMemberExpressionNode &&
-            !Node.isLabelIdentifierNode(node, parentNode);
+        return !parentNodeIsPropertyNode && !parentNodeIsMemberExpressionNode && !Node.isLabelIdentifierNode(node, parentNode);
     }
 
     /**

+ 19 - 18
src/node/NodeUtils.ts

@@ -9,6 +9,7 @@ import { TStatement } from '../types/node/TStatement';
 import { NodeType } from '../enums/NodeType';
 
 import { Node } from './Node';
+import { Nodes } from './Nodes';
 
 export class NodeUtils {
     /**
@@ -23,20 +24,20 @@ export class NodeUtils {
     ];
 
     /**
-     * @param node
+     * @param astTree
      * @return {T}
      */
-    public static addXVerbatimPropertyToLiterals <T extends ESTree.Node> (node: T): T {
-        NodeUtils.typedReplace(node, NodeType.Literal, {
-            leave: (node: ESTree.Literal) => {
-                node['x-verbatim-property'] = {
-                    content : node.raw,
+    public static addXVerbatimPropertyToLiterals <T extends ESTree.Node> (astTree: T): T {
+        NodeUtils.typedReplace(astTree, NodeType.Literal, {
+            leave: (literalNode: ESTree.Literal) => {
+                literalNode['x-verbatim-property'] = {
+                    content : literalNode.raw,
                     precedence: escodegen.Precedence.Primary
                 };
             }
         });
 
-        return node;
+        return astTree;
     }
 
     /**
@@ -152,13 +153,13 @@ export class NodeUtils {
     }
 
     /**
-     * @param node
+     * @param astTree
      * @return {T}
      */
-    public static parentize <T extends ESTree.Node> (node: T): T {
+    public static parentize <T extends ESTree.Node> (astTree: T): T {
         let isRootNode: boolean = true;
 
-        estraverse.traverse(node, {
+        estraverse.traverse(astTree, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 let value: ESTree.Node;
 
@@ -166,7 +167,7 @@ export class NodeUtils {
                     if (node.type === NodeType.Program) {
                         value = node;
                     } else {
-                        value = Node.getProgramNode(<TStatement[]>[node]);
+                        value = Nodes.getProgramNode(<TStatement[]>[node]);
                         value.parentNode = value;
                     }
 
@@ -180,35 +181,35 @@ export class NodeUtils {
             }
         });
 
-        return node;
+        return astTree;
     }
 
     /**
-     * @param node
+     * @param astTree
      * @param nodeType
      * @param visitor
      */
     public static typedReplace (
-        node: ESTree.Node,
+        astTree: ESTree.Node,
         nodeType: string,
         visitor: {enter?: (node: ESTree.Node) => void, leave?: (node: ESTree.Node) => void},
     ): void {
-        NodeUtils.typedTraverse(node, nodeType, visitor, 'replace');
+        NodeUtils.typedTraverse(astTree, nodeType, visitor, 'replace');
     }
 
     /**
-     * @param node
+     * @param astTree
      * @param nodeType
      * @param visitor
      * @param traverseType
      */
     public static typedTraverse (
-        node: ESTree.Node,
+        astTree: ESTree.Node,
         nodeType: string,
         visitor: estraverse.Visitor,
         traverseType: string = 'traverse'
     ): void {
-        (<any>estraverse)[traverseType](node, {
+        (<any>estraverse)[traverseType](astTree, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (node.type === nodeType && visitor.enter) {
                     return visitor.enter(node, parentNode);

+ 3 - 3
src/stack-trace-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor.ts

@@ -37,14 +37,14 @@ export class FunctionDeclarationCalleeDataExtractor extends AbstractCalleeDataEx
     }
 
     /**
-     * @param node
+     * @param targetNode
      * @param name
      * @returns {ESTree.BlockStatement|null}
      */
-    private getCalleeBlockStatement (node: ESTree.Node, name: string): ESTree.BlockStatement|null {
+    private getCalleeBlockStatement (targetNode: ESTree.Node, name: string): ESTree.BlockStatement|null {
         let calleeBlockStatement: ESTree.BlockStatement|null = null;
 
-        estraverse.traverse(node, {
+        estraverse.traverse(targetNode, {
             enter: (node: ESTree.Node): any => {
                 if (Node.isFunctionDeclarationNode(node) && node.id.name === name) {
                     calleeBlockStatement = node.body;

+ 3 - 3
src/stack-trace-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor.ts

@@ -41,14 +41,14 @@ export class FunctionExpressionCalleeDataExtractor extends AbstractCalleeDataExt
     }
 
     /**
-     * @param node
+     * @param targetNode
      * @param name
      * @returns {ESTree.BlockStatement|null}
      */
-    private getCalleeBlockStatement (node: ESTree.Node, name: string): ESTree.BlockStatement|null {
+    private getCalleeBlockStatement (targetNode: ESTree.Node, name: string): ESTree.BlockStatement|null {
         let calleeBlockStatement: ESTree.BlockStatement|null = null;
 
-        estraverse.traverse(node, {
+        estraverse.traverse(targetNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (
                     Node.isFunctionExpressionNode(node) &&

+ 3 - 3
src/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts

@@ -85,12 +85,12 @@ export class ObjectExpressionCalleeDataExtractor extends AbstractCalleeDataExtra
     }
 
     /**
-     * @param node
+     * @param targetNode
      * @param objectMembersCallsChain
      * @returns {ESTree.BlockStatement|null}
      */
     private getCalleeBlockStatement (
-        node: ESTree.Node,
+        targetNode: ESTree.Node,
         objectMembersCallsChain: TObjectMembersCallsChain
     ): ESTree.BlockStatement|null {
         const objectName: string|number|undefined = objectMembersCallsChain.shift();
@@ -101,7 +101,7 @@ export class ObjectExpressionCalleeDataExtractor extends AbstractCalleeDataExtra
 
         let calleeBlockStatement: ESTree.BlockStatement|null = null;
 
-        estraverse.traverse(node, {
+        estraverse.traverse(targetNode, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                 if (
                     Node.isVariableDeclaratorNode(node) &&

+ 1 - 1
src/storages/string-array/StringArrayStorage.ts

@@ -18,7 +18,7 @@ export class StringArrayStorage extends ArrayStorage <string> {
     public initialize (...args: any[]): void {
         super.initialize(args);
 
-        this.storageId = RandomGeneratorUtils.getRandomVariableName(4, false, false);
+        this.storageId = RandomGeneratorUtils.getRandomString(4, RandomGeneratorUtils.randomGeneratorPoolHexadecimal);
     }
 
     /**

+ 23 - 4
src/templates/custom-nodes/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate.ts

@@ -9,10 +9,29 @@ export function ConsoleOutputDisableExpressionTemplate (): string {
             var func = function () {};
             var that = getGlobal();
                         
-            that.console.log = func; 
-            that.console.error = func;
-            that.console.warn = func;
-            that.console.info = func;
+            if (!that.console) {
+                that.console = (function (func){ 
+                    var c = {}; 
+                    
+                    c.log = func;
+                    c.warn = func; 
+                    c.debug = func;
+                    c.info = func;
+                    c.error = func;
+                    c.exception = func;
+                    c.trace = func;
+                    
+                    return c; 
+                })(func);
+            } else {
+                that.console.log = func;
+                that.console.warn = func; 
+                that.console.debug = func;
+                that.console.info = func;
+                that.console.error = func;
+                that.console.exception = func;
+                that.console.trace = func;
+            }
         });
         
         {consoleLogDisableFunctionName}();

+ 1 - 1
src/utils/CryptUtils.ts

@@ -38,7 +38,7 @@ export class CryptUtils {
      * @param length
      * @returns {string[]}
      */
-    public static hideString(str: string, length: number): [string, string] {
+    public static hideString (str: string, length: number): [string, string] {
         const escapeRegExp: (s: string) => string = (s: string) =>
             s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
 

+ 9 - 6
src/utils/RandomGeneratorUtils.ts

@@ -8,6 +8,11 @@ export class RandomGeneratorUtils {
      */
     public static readonly randomGeneratorPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 
+    /**
+     * @type {string}
+     */
+    public static readonly randomGeneratorPoolHexadecimal: string = 'abcdef0123456789';
+
     /**
      * @type {string}
      */
@@ -87,12 +92,10 @@ export class RandomGeneratorUtils {
 
     /**
      * @param length
-     * @param withPrefix
-     * @param unique
      * @returns {string}
      */
-    public static getRandomVariableName (length: number, withPrefix: boolean, unique: boolean): string {
-        const prefix: string = withPrefix ? `_${Utils.hexadecimalPrefix}` : '';
+    public static getRandomVariableName (length: number): string {
+        const prefix: string = `_${Utils.hexadecimalPrefix}`;
         const rangeMinInteger: number = 10000;
         const rangeMaxInteger: number = 99999999;
         const randomVariableName: string = `${prefix}${(
@@ -101,8 +104,8 @@ export class RandomGeneratorUtils {
             )
         ).substr(0, length)}`;
 
-        if (unique && RandomGeneratorUtils.randomVariableNameSet.has(randomVariableName)) {
-            return RandomGeneratorUtils.getRandomVariableName(length, withPrefix, unique);
+        if (RandomGeneratorUtils.randomVariableNameSet.has(randomVariableName)) {
+            return RandomGeneratorUtils.getRandomVariableName(length);
         }
 
         RandomGeneratorUtils.randomVariableNameSet.add(randomVariableName);

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

@@ -9,7 +9,7 @@ import { readFileAsString } from '../../../helpers/readFileAsString';
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
 describe('ConsoleOutputDisableExpressionNode', () => {
-    const regExp = /(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*)*'\]\['(\\x[a-f0-9]*)*'\] *= *_0x([a-z0-9]){4,6};){4}/;
+    const regExp = /(_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*)*'\]\['(\\x[a-f0-9]*)*'\] *= *_0x([a-f0-9]){4,6};){4}/;
 
     it('should correctly append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(

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

@@ -18,7 +18,7 @@ describe('DomainLockNode', () => {
             }
         );
 
-        assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
+        assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-f0-9]){4,6} *= *new RegExp/);
     });
 
     it('should\'t append `DomainLockNode` custom node into the obfuscated code if `domainLock` option is not set', () => {
@@ -30,6 +30,6 @@ describe('DomainLockNode', () => {
             }
         );
 
-        assert.notMatch(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
+        assert.notMatch(obfuscationResult.getObfuscatedCode(), /var _0x([a-f0-9]){4,6} *= *new RegExp/);
     });
 });

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

@@ -22,7 +22,7 @@ describe('StringArrayCallsWrapper', () => {
 
         assert.match(
             obfuscationResult.getObfuscatedCode(),
-            /_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6} *- *0x0\;/
+            /_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6} *- *0x0\;/
         );
     });
 });

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

@@ -19,7 +19,7 @@ describe('StringArrayNode', () => {
             }
         );
 
-        assert.match(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
+        assert.match(obfuscationResult.getObfuscatedCode(), /^var _0x([a-f0-9]){4} *= *\[/);
     });
 
     it('should\'t append `StringArrayNode` custom node into the obfuscated code if `stringArray` option is not set', () => {
@@ -31,6 +31,6 @@ describe('StringArrayNode', () => {
             }
         );
 
-        assert.notMatch(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
+        assert.notMatch(obfuscationResult.getObfuscatedCode(), /^var _0x([a-f0-9]){4} *= *\[/);
     });
 });

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

@@ -20,7 +20,7 @@ describe('StringArrayRotateFunctionNode', () => {
             }
         );
 
-        assert.match(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
+        assert.match(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-f0-9]){4,6}\) *\{/);
     });
 
     it('should\'t append `StringArrayRotateFunctionNode` custom node into the obfuscated code if `rotateStringArray` option is not set', () => {
@@ -34,6 +34,6 @@ describe('StringArrayRotateFunctionNode', () => {
             }
         );
 
-        assert.notMatch(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
+        assert.notMatch(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-f0-9]){4,6}\) *\{/);
     });
 });

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

@@ -28,11 +28,11 @@ describe('BlockStatementControlFlowTransformer', () => {
             const statementRegExp4: RegExp = /console\['log'\]\(0x4\);/;
             const statementRegExp5: RegExp = /console\['log'\]\(0x5\);/;
 
-            const switchCaseRegExp: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/;
+            const switchCaseRegExp: RegExp = /switch *\(_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\+\+\]\) *\{/;
             const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
             const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
 
-            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-z0-9]){4,6} *= *'(.*?)'/;
+            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *'(.*?)'/;
             const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
             const switchCaseMapMatch: string = switchCaseMapMatches[1];
             const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
@@ -73,11 +73,11 @@ describe('BlockStatementControlFlowTransformer', () => {
             const statementRegExp4: RegExp = /console\['log'\]\(0x4\);/;
             const statementRegExp5: RegExp = /console\['log'\]\(0x5\);/;
 
-            const switchCaseRegExp: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\+\+\]\) *\{/;
+            const switchCaseRegExp: RegExp = /switch *\(_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\+\+\]\) *\{/;
             const switchCaseLengthRegExp: RegExp = /case *'[0-5]': *console\['log'\]\(0x[0-6]\);/g;
             const switchCaseLength: number = obfuscatedCode.match(switchCaseLengthRegExp)!.length;
 
-            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-z0-9]){4,6} *= *'(.*?)'/;
+            const switchCaseMapRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *'(.*?)'/;
             const switchCaseMapMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(switchCaseMapRegExp);
             const switchCaseMapMatch: string = switchCaseMapMatches[1];
             const switchCaseMap: string[] = switchCaseMapMatch.replace(/\\x7c/g, '|').split('|').sort();
@@ -129,7 +129,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *const *_0x([a-z0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *const *_0x([a-f0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
 
             it('shouldn\'t transform block statement if block statement contain variable declaration with `const` kind', () => {
                 assert.match(obfuscatedCode, statementRegExp);
@@ -147,7 +147,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *let *_0x([a-z0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *let *_0x([a-f0-9]){4,6} *= *0x1; *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
 
             it('shouldn\'t transform block statement if block statement contain variable declaration with `let` kind', () => {
                 assert.match(obfuscatedCode, statementRegExp);
@@ -201,7 +201,7 @@ describe('BlockStatementControlFlowTransformer', () => {
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 
-            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-z0-9]){4,6} *\( *\) *\{ *\} *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
+            const statementRegExp: RegExp = /^\(function *\( *\) *\{ *function *_0x([a-f0-9]){4,6} *\( *\) *\{ *\} *console\['(\\x[a-f0-9]*){3}'\]\(0x1\);/;
 
             it('shouldn\'t transform block statement if block statement contain function declaration', () => {
                 assert.match(obfuscatedCode, statementRegExp);
@@ -221,7 +221,7 @@ describe('BlockStatementControlFlowTransformer', () => {
                 }
             );
 
-            const regExp1: RegExp = /switch *\(_0x([a-z0-9]){4,6}\[_0x([a-z0-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 transformedStatementMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.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 controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-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}\['(\\x[a-f0-9]*){3}'\]\(0x1, *0x2\);/;
 
             it('should replace binary expression node by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -47,8 +47,8 @@ describe('BinaryExpressionControlFlowReplacer', () => {
                         }
                     );
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(0x1, *0x2\);/;
-                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-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}\['(\\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 firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     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 controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(_0x([a-z0-9]){4,6}, *0x1, *0x2\);/;
+            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\);/;
 
             it('should replace call expression node by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -47,8 +47,8 @@ describe('CallExpressionControlFlowReplacer', () => {
                         }
                     );
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(_0x([a-z0-9]){4,6}, *0x1, *0x2\);/;
-                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(_0x([a-z0-9]){4,6}, *0x2, *0x3\);/;
+                    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 firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
@@ -80,7 +80,7 @@ describe('CallExpressionControlFlowReplacer', () => {
                 }
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\['\\x73\\x75\\x6d'\]\(0x1, *0x2\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\\x73\\x75\\x6d'\]\(0x1, *0x2\);/;
 
             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);

+ 5 - 5
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 controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(!!\[\], *!\[\]\);/;
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(!!\[\], *!\[\]\);/;
 
             it('should replace logical expression node by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -47,8 +47,8 @@ describe('LogicalExpressionControlFlowReplacer', () => {
                         }
                     );
                     const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(!!\[\], *!\[\]\);/;
-                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(!\[\], *!!\[\]\);/;
+                    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 firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
                     const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
@@ -80,7 +80,7 @@ describe('LogicalExpressionControlFlowReplacer', () => {
                 }
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(!_0x([a-z0-9]){4,6}, *!_0x([a-z0-9]){4,6}\);/;
+            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}\);/;
 
             it('should replace logical expression node with unary expression by call to control flow storage node', () => {
                 assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
@@ -97,7 +97,7 @@ describe('LogicalExpressionControlFlowReplacer', () => {
                 }
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const regExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\[_0x([a-z0-9]){4,6}\] *&& *!\[\];/;
+            const regExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\[_0x([a-f0-9]){4,6}\] *&& *!\[\];/;
 
             it('shouldn\'t replace prohibited expression nodes', () => {
                 assert.match(obfuscatedCode, regExp);

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

@@ -9,7 +9,7 @@ import { readFileAsString } from '../../../../helpers/readFileAsString';
 import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscator';
 
 describe('FunctionControlFlowTransformer', () => {
-    const variableMatch: string = '_0x([a-z0-9]){4,6}';
+    const variableMatch: string = '_0x([a-f0-9]){4,6}';
     const rootControlFlowStorageNodeMatch: string = `` +
         `var *${variableMatch} *= *\\{` +
             `'(\\\\x[a-f0-9]*){3}' *: *function *${variableMatch} *\\(${variableMatch}, *${variableMatch}\\) *\\{` +
@@ -171,7 +171,7 @@ describe('FunctionControlFlowTransformer', () => {
             );
             const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
             const controlFlowStorageMatch: RegExp = new RegExp(rootControlFlowStorageNodeMatch);
-            const regexp: RegExp = /var *_0x([a-z0-9]){4,6} *= *0x1 *\+ *0x2;/;
+            const regexp: RegExp = /var *_0x([a-f0-9]){4,6} *= *0x1 *\+ *0x2;/;
 
             it('shouldn\'t add `control flow storage` node to the obfuscated code when threshold is 0', () => {
                 assert.match(obfuscatedCode, regexp);

+ 20 - 2
test/functional-tests/node-transformers/obfuscation-transformers/catch-clause-transformer/CatchClauseTransformer.spec.ts

@@ -17,8 +17,8 @@ describe('CatchClauseTransformer', () => {
             }
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-        const paramNameRegExp: RegExp = /catch *\((_0x([a-z0-9]){4,6})\) *\{/;
-        const bodyParamNameRegExp: RegExp = /console\['\\x6c\\x6f\\x67'\]\((_0x([a-z0-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})\);/;
 
         it('should transform catch clause node', () => {
             assert.match(obfuscatedCode, paramNameRegExp);
@@ -37,4 +37,22 @@ describe('CatchClauseTransformer', () => {
             assert.equal(firstMatch, secondMatch);
         });
     });
+
+    describe('object pattern as parameter', () => {
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/object-pattern-as-parameter.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+        it('shouldn\'t transform function parameter object pattern identifier', () => {
+            const functionParameterMatch: RegExp = /\} *catch *\(\{ *name *\}\) *\{/;
+            const functionBodyMatch: RegExp = /return *name;/;
+
+            assert.match(obfuscatedCode, functionParameterMatch);
+            assert.match(obfuscatedCode, functionBodyMatch);
+        });
+    });
 });

+ 7 - 0
test/functional-tests/node-transformers/obfuscation-transformers/catch-clause-transformer/fixtures/object-pattern-as-parameter.js

@@ -0,0 +1,7 @@
+(function () {
+    try {
+
+    } catch ({ name }) {
+        return name;
+    }
+})();

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

@@ -32,9 +32,9 @@ describe('FunctionDeclarationTransformer', () => {
 
         it('should transform function name if `functionDeclaration` parent block scope is not a `ProgramNode`', () => {
             const functionNameIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/function *_0x[a-z0-9]{4,6} *\(\) *\{/);
+                .match(/function *_0x[a-f0-9]{4,6} *\(\) *\{/);
             const functionCallIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/_0x[a-z0-9]{4,6} *\( *\);/);
+                .match(/_0x[a-f0-9]{4,6} *\( *\);/);
 
             const functionParamIdentifierName: string = (<RegExpMatchArray>functionNameIdentifierMatch)[1];
             const functionBodyIdentifierName: string = (<RegExpMatchArray>functionCallIdentifierMatch)[1];

+ 20 - 2
test/functional-tests/node-transformers/obfuscation-transformers/function-transformer/FunctionTransformer.spec.ts

@@ -20,9 +20,9 @@ describe('FunctionTransformer', () => {
 
         it('should correct transform both function parameter identifier and function body identifier with same name', () => {
             const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/var _0x[a-z0-9]{4,6} *= *function *\((_0x[a-z0-9]{4,6})\) *\{/);
+                .match(/var _0x[a-f0-9]{4,6} *= *function *\((_0x[a-f0-9]{4,6})\) *\{/);
             const functionBodyIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{4,6})\)/);
+                .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-f0-9]{4,6})\)/);
 
             const functionParamIdentifierName: string = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
             const functionBodyIdentifierName: string = (<RegExpMatchArray>functionBodyIdentifierMatch)[1];
@@ -34,4 +34,22 @@ describe('FunctionTransformer', () => {
             assert.equal(/variable *= *0x6;/.test(obfuscatedCode), true);
         });
     });
+
+    describe('object pattern as parameter', () => {
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/object-pattern-as-parameter.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+        it('shouldn\'t transform function parameter object pattern identifier', () => {
+            const functionParameterMatch: RegExp = /function *\(\{ *bar *\}\) *\{/;
+            const functionBodyMatch: RegExp = /return *bar;/;
+
+            assert.match(obfuscatedCode, functionParameterMatch);
+            assert.match(obfuscatedCode, functionBodyMatch);
+        });
+    });
 });

+ 5 - 0
test/functional-tests/node-transformers/obfuscation-transformers/function-transformer/fixtures/object-pattern-as-parameter.js

@@ -0,0 +1,5 @@
+(function () {
+    var test = function ({ bar }) {
+        return bar;
+    }
+})();

+ 3 - 3
test/functional-tests/node-transformers/obfuscation-transformers/labeled-statement-transformer/LabeledStatementTransformer.spec.ts

@@ -17,9 +17,9 @@ describe('LabeledStatementTransformer', () => {
             }
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-        const labeledStatementRegExp: RegExp = /(_0x([a-z0-9]){4,6}): *\{/;
-        const continueStatementRegExp: RegExp = /continue *(_0x([a-z0-9]){4,6});/;
-        const breakStatementRegExp: RegExp = /break *(_0x([a-z0-9]){4,6});/;
+        const labeledStatementRegExp: RegExp = /(_0x([a-f0-9]){4,6}): *\{/;
+        const continueStatementRegExp: RegExp = /continue *(_0x([a-f0-9]){4,6});/;
+        const breakStatementRegExp: RegExp = /break *(_0x([a-f0-9]){4,6});/;
 
         it('should transform `labeledStatement` identifier', () => {
             assert.match(obfuscatedCode, labeledStatementRegExp);

+ 10 - 10
test/functional-tests/node-transformers/obfuscation-transformers/literal-transformer/LiteralTransformer.spec.ts

@@ -33,9 +33,9 @@ describe('LiteralTransformer', () => {
 
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-z0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
+                /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
             );
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
+            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', () => {
@@ -50,9 +50,9 @@ describe('LiteralTransformer', () => {
 
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-z0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
+                /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
             );
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-z0-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` is disabled', () => {
@@ -68,9 +68,9 @@ describe('LiteralTransformer', () => {
 
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-z0-9]){4} *= *\['test'\];/
+                /^var *_0x([a-f0-9]){4} *= *\['test'\];/
             );
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-z0-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', () => {
@@ -126,9 +126,9 @@ describe('LiteralTransformer', () => {
 
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
-                /^var *_0x([a-z0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/
+                /^var *_0x([a-f0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/
             );
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/);
         });
 
         it('should replace literal node value with value from string array encoded using rc4', () => {
@@ -144,7 +144,7 @@ describe('LiteralTransformer', () => {
 
             assert.match(
                 obfuscationResult.getObfuscatedCode(),
-                /var *test *= *_0x([a-z0-9]){4}\('0x0', '(\\x[a-f0-9]*){4}'\);/
+                /var *test *= *_0x([a-f0-9]){4}\('0x0', '(\\x[a-f0-9]*){4}'\);/
             );
         });
 
@@ -161,7 +161,7 @@ describe('LiteralTransformer', () => {
                 }
             );
 
-            const regExp1: RegExp = /var *test *= *_0x([a-z0-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 stringArrayMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp1)!.length;
             const noStringArrayMatchesLength = obfuscationResult.getObfuscatedCode().match(regExp2)!.length;

+ 4 - 4
test/functional-tests/node-transformers/obfuscation-transformers/member-expression-transformer/MemberExpressionTransformer.spec.ts

@@ -31,8 +31,8 @@ describe('MemberExpressionTransformer', () => {
                 }
             );
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-z0-9]){4}\('0x0'\)\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-f0-9]){4}\('0x0'\)\];/);
         });
     });
 
@@ -47,8 +47,8 @@ describe('MemberExpressionTransformer', () => {
                 }
             );
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-z0-9]){4}\('0x0'\)\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[_0x([a-f0-9]){4}\('0x0'\)\];/);
         });
 
         it('should ignore square brackets call with identifier value', () => {

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

@@ -32,8 +32,8 @@ describe('MethodDefinitionTransformer', () => {
             }
         );
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4} *= *\['\\x62\\x61\\x72'\];/);
-        assert.match(obfuscationResult.getObfuscatedCode(),  /\[_0x([a-z0-9]){4}\('0x0'\)\]\(\)\{\}/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-f0-9]){4} *= *\['\\x62\\x61\\x72'\];/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /\[_0x([a-f0-9]){4}\('0x0'\)\]\(\)\{\}/);
     });
 
     it('should not transform method definition node with `constructor` key', () => {

+ 1 - 1
test/functional-tests/node-transformers/obfuscation-transformers/object-expression-transformer/ObjectExpressionTransformer.spec.ts

@@ -41,7 +41,7 @@ describe('ObjectExpressionTransformer', () => {
 
         assert.match(
             obfuscationResult.getObfuscatedCode(),
-            /var *_0x[a-z0-9]{4,6} *= *\{'\\x61': *_0x[a-z0-9]{4,6}\, *'\\x62': *_0x[a-z0-9]{4,6}\};/
+            /var *_0x[a-f0-9]{4,6} *= *\{'\\x61': *_0x[a-f0-9]{4,6}\, *'\\x62': *_0x[a-f0-9]{4,6}\};/
         );
     });
 });

+ 99 - 38
test/functional-tests/node-transformers/obfuscation-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts

@@ -17,8 +17,8 @@ describe('VariableDeclarationTransformer', () => {
             }
         );
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4,6} *= *'\\x61\\x62\\x63';/);
-        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
+        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}\);/);
     });
 
     it('should not transform `variableDeclaration` node if parent block scope node is `Program` node', () => {
@@ -41,7 +41,7 @@ describe('VariableDeclarationTransformer', () => {
             }
         );
 
-        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
+        assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_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', () => {
@@ -68,57 +68,100 @@ describe('VariableDeclarationTransformer', () => {
         });
 
         it('should transform variable call (`identifier` node) before variable declaration if this call is inside function body', () => {
-            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\['\\x69\\x74\\x65\\x6d'\]\);/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-f0-9]){4,6}\['\\x69\\x74\\x65\\x6d'\]\);/);
         });
 
         it('should not transform variable call (`identifier` node) before variable declaration', () => {
-            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-f0-9]){4,6}\);/);
         });
     });
 
     describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
-        let obfuscationResult: IObfuscationResult,
-            functionParamIdentifierName: string|null,
-            innerFunctionParamIdentifierName: string|null,
-            constructorIdentifierName: string|null,
-            objectIdentifierName: string|null,
-            variableDeclarationIdentifierName: string|null;
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/variable-call-before-variable-declaration-2.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+        const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/function *_0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\,(_0x[a-f0-9]{4,6})\) *\{/);
+        const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/function _0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\) *\{/);
+        const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-f0-9]{4,6})\)/);
+        const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/return\{'\\x74':(_0x[a-f0-9]{4,6})\}/);
+        const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/var *(_0x[a-f0-9]{4,6});/);
+
+        const outerFunctionParamIdentifierName: string|null = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
+        const innerFunctionParamIdentifierName: string|null = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
+        const constructorIdentifierName: string|null = (<RegExpMatchArray>constructorIdentifierMatch)[1];
+        const objectIdentifierName: string|null = (<RegExpMatchArray>objectIdentifierMatch)[1];
+        const variableDeclarationIdentifierName: string|null = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
+
+        it('should\'t name variables inside inner function with names from outer function params', () => {
+            assert.notEqual(outerFunctionParamIdentifierName, constructorIdentifierName);
+            assert.notEqual(outerFunctionParamIdentifierName, innerFunctionParamIdentifierName);
+        });
 
-        beforeEach(() => {
-            obfuscationResult = JavaScriptObfuscator.obfuscate(
-                readFileAsString(__dirname + '/fixtures/variable-call-before-variable-declaration-2.js'),
-                {
-                    ...NO_CUSTOM_NODES_PRESET
-                }
-            );
+        it('should correct transform variables inside outer function body', () => {
+            assert.equal(outerFunctionParamIdentifierName, objectIdentifierName);
+            assert.equal(outerFunctionParamIdentifierName, variableDeclarationIdentifierName);
+        });
+
+        it('should correct transform variables inside inner function body', () => {
+            assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
         });
 
-        it('should correct transform variables inside function body', () => {
-            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
-            const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/function *_0x[a-z0-9]{4,6} *\((_0x[a-z0-9]{4,6})\,(_0x[a-z0-9]{4,6})\) *\{/);
-            const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/function _0x[a-z0-9]{4,6} *\((_0x[a-z0-9]{4,6})\) *\{/);
-            const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{4,6})\)/);
-            const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/return\{'\\x74':(_0x[a-z0-9]{4,6})\}/);
-            const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
-                .match(/var *(_0x[a-z0-9]{4,6});/);
-
-            functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
-            innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
-            constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
-            objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
-            variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
+        it('should keep equal names after transformation for variables with same names', () => {
+            assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
+        });
+    });
 
+    describe(`variable calls before variable declaration when catch clause param has the same name as variables name`, () => {
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/variable-call-before-variable-declaration-3.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+        const catchClauseParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/catch *\((_0x[a-f0-9]{4,6})\) *\{/);
+        const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/function _0x[a-f0-9]{4,6} *\((_0x[a-f0-9]{4,6})\) *\{/);
+        const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-f0-9]{4,6})\)/);
+        const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/return\{'\\x74':(_0x[a-f0-9]{4,6})\}/);
+        const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
+            .match(/var *(_0x[a-f0-9]{4,6});/);
+
+        const functionParamIdentifierName: string|null = (<RegExpMatchArray>catchClauseParamIdentifierMatch)[1];
+        const innerFunctionParamIdentifierName: string|null = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
+        const constructorIdentifierName: string|null = (<RegExpMatchArray>constructorIdentifierMatch)[1];
+        const objectIdentifierName: string|null = (<RegExpMatchArray>objectIdentifierMatch)[1];
+        const variableDeclarationIdentifierName: string|null = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
+
+        it('should\'t name variables inside inner function with names from catch clause param', () => {
             assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
             assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
+        });
 
+        it('should correct transform variables inside catch clause body', () => {
             assert.equal(functionParamIdentifierName, objectIdentifierName);
             assert.equal(functionParamIdentifierName, variableDeclarationIdentifierName);
+        });
 
+        it('should correct transform variables inside inner function body', () => {
             assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
+        });
+
+        it('should keep equal names after transformation for variables with same names', () => {
             assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
         });
     });
@@ -132,7 +175,7 @@ describe('VariableDeclarationTransformer', () => {
                 }
             );
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /var _0x([a-z0-9]){4,6} *= *\{'\\x74\\x65\\x73\\x74/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /var _0x([a-f0-9]){4,6} *= *\{'\\x74\\x65\\x73\\x74/);
         });
 
         it('shouldn\'t replace computed member expression identifier', () => {
@@ -143,7 +186,25 @@ describe('VariableDeclarationTransformer', () => {
                 }
             );
 
-            assert.match(obfuscationResult.getObfuscatedCode(),  /_0x([a-z0-9]){4,6}\['\\x74\\x65\\x73\\x74'\]/);
+            assert.match(obfuscationResult.getObfuscatedCode(),  /_0x([a-f0-9]){4,6}\['\\x74\\x65\\x73\\x74'\]/);
+        });
+    });
+
+    describe('object pattern as variable declarator', () => {
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            readFileAsString(__dirname + '/fixtures/object-pattern.js'),
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
+        );
+        const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+
+        it('shouldn\'t transform object pattern variable declarator', () => {
+            const objectPatternVariableDeclarator: RegExp = /var *\{ *bar *\} *= *\{ *'\\x62\\x61\\x72' *: *'\\x66\\x6f\\x6f' *\};/;
+            const variableUsageMatch: RegExp = /console\['\\x6c\\x6f\\x67'\]\(bar\);/;
+
+            assert.match(obfuscatedCode, objectPatternVariableDeclarator);
+            assert.match(obfuscatedCode, variableUsageMatch);
         });
     });
 });

+ 4 - 0
test/functional-tests/node-transformers/obfuscation-transformers/variable-declaration-transformer/fixtures/object-pattern.js

@@ -0,0 +1,4 @@
+(function () {
+    var { bar } = { bar: 'foo' };
+    console.log(bar);
+})();

+ 14 - 0
test/functional-tests/node-transformers/obfuscation-transformers/variable-declaration-transformer/fixtures/variable-call-before-variable-declaration-3.js

@@ -0,0 +1,14 @@
+(function () {
+    try {
+
+    } catch (t) {
+        return function () {
+            function baz (t) {
+                console.log(t);
+            }
+
+            return {t: t};
+            var t;
+        }();
+    }
+})();

+ 2 - 2
test/unit-tests/utils/random-generator-utils/RandomGeneratorUtils.spec.ts

@@ -5,8 +5,8 @@ import { RandomGeneratorUtils } from '../../../../src/utils/RandomGeneratorUtils
 describe('RandomGeneratorUtils', () => {
     describe('getRandomVariableName (length: number = 6): string', () => {
         it('should return a string of given length with random variable name', () => {
-            assert.match(RandomGeneratorUtils.getRandomVariableName(4, true, false), /^_0x(\w){4}$/);
-            assert.match(RandomGeneratorUtils.getRandomVariableName(6, true, true), /^_0x(\w){4,6}$/);
+            assert.match(RandomGeneratorUtils.getRandomVariableName(4), /^_0x(\w){4}$/);
+            assert.match(RandomGeneratorUtils.getRandomVariableName(6), /^_0x(\w){4,6}$/);
         });
     });
 });

+ 5 - 1
tslint.json

@@ -29,6 +29,7 @@
       true,
       "always-prefix"
     ],
+    "import-spacing": true,
     "jsdoc-format": true,
     "label-position": true,
     "max-line-length": false,
@@ -66,7 +67,7 @@
     "no-parameter-properties": true,
     "no-reference": true,
     "no-require-imports": false,
-    "no-shadowed-variable": false,
+    "no-shadowed-variable": true,
     "no-string-literal": true,
     "no-string-throw": true,
     "no-switch-case-fall-through": false,
@@ -89,6 +90,7 @@
     "quotemark": false,
     "radix": true,
     "semicolon": [true, "always"],
+    "space-before-function-paren": true,
     "switch-default": false,
     "trailing-comma": false,
     "triple-equals": [
@@ -122,6 +124,8 @@
         "variable-declaration": "space"
       }
     ],
+    "typeof-compare": true,
+    "unified-signatures": true,
     "use-isnan": true,
     "variable-name": false,
     "whitespace": [

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff