Przeglądaj źródła

ts 2.1 refactoring + first runtime test

sanex3339 8 lat temu
rodzic
commit
4b3bc9b81b
46 zmienionych plików z 725 dodań i 346 usunięć
  1. 139 80
      dist/index.js
  2. 3 4
      src/JavaScriptObfuscatorInternal.ts
  3. 4 1
      src/cli/JavaScriptObfuscatorCLI.ts
  4. 3 2
      src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts
  5. 3 2
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  6. 3 2
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  7. 3 2
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  8. 33 15
      src/options/OptionsNormalizer.ts
  9. 4 5
      src/stack-trace-analyzer/StackTraceAnalyzer.ts
  10. 14 12
      test/dev/dev.ts
  11. 182 0
      test/fixtures/runtime/sha256.js
  12. 23 13
      test/functional-tests/JavaScriptObfuscator.spec.ts
  13. 2 2
      test/functional-tests/JavaScriptObfuscatorCLI.spec.ts
  14. 13 15
      test/functional-tests/JavaScriptObfuscatorInternal.spec.ts
  15. 9 6
      test/functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec.ts
  16. 8 6
      test/functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec.ts
  17. 5 4
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayCallsWrapper.spec.ts
  18. 8 6
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayNode.spec.ts
  19. 8 6
      test/functional-tests/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.spec.ts
  20. 5 3
      test/functional-tests/node-transformers/node-obfuscators/CatchClauseObfuscator.spec.ts
  21. 5 3
      test/functional-tests/node-transformers/node-obfuscators/FunctionDeclarationObfuscator.spec.ts
  22. 18 16
      test/functional-tests/node-transformers/node-obfuscators/FunctionObfuscator.spec.ts
  23. 5 3
      test/functional-tests/node-transformers/node-obfuscators/LabeledStatementObfuscator.spec.ts
  24. 26 17
      test/functional-tests/node-transformers/node-obfuscators/LiteralObfuscator.spec.ts
  25. 14 8
      test/functional-tests/node-transformers/node-obfuscators/MemberExpressionObfuscator.spec.ts
  26. 11 6
      test/functional-tests/node-transformers/node-obfuscators/MethodDefinitionObfuscator.spec.ts
  27. 14 6
      test/functional-tests/node-transformers/node-obfuscators/ObjectExpressionObfuscator.spec.ts
  28. 45 29
      test/functional-tests/node-transformers/node-obfuscators/VariableDeclarationObfuscator.spec.ts
  29. 2 3
      test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts
  30. 2 3
      test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts
  31. 2 2
      test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts
  32. 5 0
      test/index.spec.ts
  33. 2 2
      test/performance-tests/JavaScriptObfuscatorPerformance.spec.ts
  34. 28 0
      test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts
  35. 2 2
      test/unit-tests/ObfuscationResult.spec.ts
  36. 53 37
      test/unit-tests/OptionsNormalizer.spec.ts
  37. 2 2
      test/unit-tests/SourceMapCorrector.spec.ts
  38. 2 2
      test/unit-tests/cli/CLIUtils.spec.ts
  39. 2 2
      test/unit-tests/decorators/Initializable.spec.ts
  40. 2 3
      test/unit-tests/node/NodeAppender.spec.ts
  41. 2 3
      test/unit-tests/node/NodeUtils.spec.ts
  42. 1 3
      test/unit-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts
  43. 2 2
      test/unit-tests/storages/ControlFlowStorage.spec.ts
  44. 2 2
      test/unit-tests/utils/CryptUtils.spec.ts
  45. 2 2
      test/unit-tests/utils/RandomGeneratorUtils.spec.ts
  46. 2 2
      test/unit-tests/utils/Utils.spec.ts

+ 139 - 80
dist/index.js

@@ -898,7 +898,7 @@ var JavaScriptObfuscator = function () {
     }
 
     _createClass(JavaScriptObfuscator, null, [{
-        key: "obfuscate",
+        key: 'obfuscate',
         value: function obfuscate(sourceCode) {
             var inputOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
 
@@ -907,7 +907,7 @@ var JavaScriptObfuscator = function () {
             return javaScriptObfuscator.obfuscate(sourceCode);
         }
     }, {
-        key: "runCLI",
+        key: 'runCLI',
         value: function runCLI(argv) {
             new JavaScriptObfuscatorCLI_1.JavaScriptObfuscatorCLI(argv).run();
         }
@@ -1953,6 +1953,15 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
     var c = arguments.length,
         r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
@@ -1974,7 +1983,7 @@ var ServiceIdentifiers_1 = __webpack_require__(1);
 var esprima = __webpack_require__(36);
 var escodegen = __webpack_require__(17);
 var RandomGeneratorUtils_1 = __webpack_require__(2);
-var JavaScriptObfuscatorInternal_1 = function () {
+var JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal_1 = function () {
     function JavaScriptObfuscatorInternal(obfuscator, sourceMapCorrector, options) {
         _classCallCheck(this, JavaScriptObfuscatorInternal);
 
@@ -1986,7 +1995,7 @@ var JavaScriptObfuscatorInternal_1 = function () {
     _createClass(JavaScriptObfuscatorInternal, [{
         key: "generateCode",
         value: function generateCode(sourceCode, astTree) {
-            var escodegenParams = Object.assign({}, JavaScriptObfuscatorInternal_1.escodegenParams);
+            var escodegenParams = __assign({}, JavaScriptObfuscatorInternal_1.escodegenParams);
             if (this.options.sourceMap) {
                 escodegenParams.sourceMap = 'sourceMap';
                 escodegenParams.sourceContent = sourceCode;
@@ -2018,7 +2027,6 @@ var JavaScriptObfuscatorInternal_1 = function () {
 
     return JavaScriptObfuscatorInternal;
 }();
-var JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal_1;
 JavaScriptObfuscatorInternal.escodegenParams = {
     verbatim: 'x-verbatim-property',
     sourceMapWithCode: true
@@ -2026,8 +2034,9 @@ JavaScriptObfuscatorInternal.escodegenParams = {
 JavaScriptObfuscatorInternal.esprimaParams = {
     loc: true
 };
-JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IObfuscator)), __param(1, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.ISourceMapCorrector)), __param(2, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata('design:paramtypes', [Object, Object, Object])], JavaScriptObfuscatorInternal);
+JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IObfuscator)), __param(1, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.ISourceMapCorrector)), __param(2, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object, Object, Object])], JavaScriptObfuscatorInternal);
 exports.JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal;
+var JavaScriptObfuscatorInternal_1;
 
 /***/ },
 /* 39 */
@@ -2361,6 +2370,15 @@ var _createClass = (function () { function defineProperties(target, props) { for
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var commander = __webpack_require__(115);
 var path = __webpack_require__(37);
 var SourceMapMode_1 = __webpack_require__(19);
@@ -2406,7 +2424,7 @@ var JavaScriptObfuscatorCLI = function () {
                 }
                 inputOptions[option] = this.commands[option];
             }
-            return Object.assign({}, DefaultPreset_1.DEFAULT_PRESET, inputOptions);
+            return __assign({}, DefaultPreset_1.DEFAULT_PRESET, inputOptions);
         }
     }, {
         key: "configureCommands",
@@ -2553,12 +2571,12 @@ var InversifyContainerFacade = function () {
     }
 
     _createClass(InversifyContainerFacade, [{
-        key: "get",
+        key: 'get',
         value: function get(serviceIdentifier) {
             return this.container.get(serviceIdentifier);
         }
     }, {
-        key: "getNamed",
+        key: 'getNamed',
         value: function getNamed(serviceIdentifier, named) {
             return this.container.getNamed(serviceIdentifier, named);
         }
@@ -3431,6 +3449,15 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
 
 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
     var c = arguments.length,
         r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
@@ -3477,9 +3504,7 @@ var NodeCallsControllerFunctionNode = function (_AbstractCustomNode_) {
             if (this.appendEvent === ObfuscationEvents_1.ObfuscationEvents.AfterObfuscation) {
                 return JavaScriptObfuscator_1.JavaScriptObfuscator.obfuscate(format(SingleNodeCallControllerTemplate_1.SingleNodeCallControllerTemplate(), {
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
-                }), Object.assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, {
-                    seed: this.options.seed
-                })).getObfuscatedCode();
+                }), __assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, { seed: this.options.seed })).getObfuscatedCode();
             }
             return format(SingleNodeCallControllerTemplate_1.SingleNodeCallControllerTemplate(), {
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
@@ -3489,9 +3514,9 @@ var NodeCallsControllerFunctionNode = function (_AbstractCustomNode_) {
 
     return NodeCallsControllerFunctionNode;
 }(AbstractCustomNode_1.AbstractCustomNode);
-__decorate([Initializable_1.initializable(), __metadata('design:type', String)], NodeCallsControllerFunctionNode.prototype, "appendEvent", void 0);
-__decorate([Initializable_1.initializable(), __metadata('design:type', String)], NodeCallsControllerFunctionNode.prototype, "callsControllerFunctionName", void 0);
-NodeCallsControllerFunctionNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata('design:paramtypes', [Object])], NodeCallsControllerFunctionNode);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], NodeCallsControllerFunctionNode.prototype, "appendEvent", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], NodeCallsControllerFunctionNode.prototype, "callsControllerFunctionName", void 0);
+NodeCallsControllerFunctionNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], NodeCallsControllerFunctionNode);
 exports.NodeCallsControllerFunctionNode = NodeCallsControllerFunctionNode;
 
 /***/ },
@@ -3511,6 +3536,15 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
 
 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
     var c = arguments.length,
         r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
@@ -3556,16 +3590,14 @@ var SelfDefendingUnicodeNode = function (_AbstractCustomNode_) {
             return JavaScriptObfuscator_1.JavaScriptObfuscator.obfuscate(format(SelfDefendingTemplate_1.SelfDefendingTemplate(), {
                 selfDefendingFunctionName: RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
-            }), Object.assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, {
-                seed: this.options.seed
-            })).getObfuscatedCode();
+            }), __assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, { seed: this.options.seed })).getObfuscatedCode();
         }
     }]);
 
     return SelfDefendingUnicodeNode;
 }(AbstractCustomNode_1.AbstractCustomNode);
-__decorate([Initializable_1.initializable(), __metadata('design:type', String)], SelfDefendingUnicodeNode.prototype, "callsControllerFunctionName", void 0);
-SelfDefendingUnicodeNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata('design:paramtypes', [Object])], SelfDefendingUnicodeNode);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], SelfDefendingUnicodeNode.prototype, "callsControllerFunctionName", void 0);
+SelfDefendingUnicodeNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], SelfDefendingUnicodeNode);
 exports.SelfDefendingUnicodeNode = SelfDefendingUnicodeNode;
 
 /***/ },
@@ -3680,6 +3712,15 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
 
 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
     var c = arguments.length,
         r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
@@ -3734,9 +3775,7 @@ var StringArrayCallsWrapper = function (_AbstractCustomNode_) {
                 decodeNodeTemplate: decodeNodeTemplate,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayName: this.stringArrayName
-            }), Object.assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, {
-                seed: this.options.seed
-            })).getObfuscatedCode();
+            }), __assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, { seed: this.options.seed })).getObfuscatedCode();
         }
     }, {
         key: "getNodeIdentifier",
@@ -3777,10 +3816,10 @@ var StringArrayCallsWrapper = function (_AbstractCustomNode_) {
 
     return StringArrayCallsWrapper;
 }(AbstractCustomNode_1.AbstractCustomNode);
-__decorate([Initializable_1.initializable(), __metadata('design:type', Object)], StringArrayCallsWrapper.prototype, "stringArray", void 0);
-__decorate([Initializable_1.initializable(), __metadata('design:type', String)], StringArrayCallsWrapper.prototype, "stringArrayCallsWrapperName", void 0);
-__decorate([Initializable_1.initializable(), __metadata('design:type', String)], StringArrayCallsWrapper.prototype, "stringArrayName", void 0);
-StringArrayCallsWrapper = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata('design:paramtypes', [Object])], StringArrayCallsWrapper);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayCallsWrapper.prototype, "stringArray", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayCallsWrapper.prototype, "stringArrayCallsWrapperName", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayCallsWrapper.prototype, "stringArrayName", void 0);
+StringArrayCallsWrapper = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], StringArrayCallsWrapper);
 exports.StringArrayCallsWrapper = StringArrayCallsWrapper;
 
 /***/ },
@@ -3800,6 +3839,15 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
 
 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
     var c = arguments.length,
         r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
@@ -3863,18 +3911,16 @@ var StringArrayRotateFunctionNode = function (_AbstractCustomNode_) {
                 stringArrayName: this.stringArrayName,
                 stringArrayRotateValue: Utils_1.Utils.decToHex(this.stringArrayRotateValue),
                 whileFunctionName: whileFunctionName
-            }), Object.assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, {
-                seed: this.options.seed
-            })).getObfuscatedCode();
+            }), __assign({}, NoCustomNodesPreset_1.NO_CUSTOM_NODES_PRESET, { seed: this.options.seed })).getObfuscatedCode();
         }
     }]);
 
     return StringArrayRotateFunctionNode;
 }(AbstractCustomNode_1.AbstractCustomNode);
-__decorate([Initializable_1.initializable(), __metadata('design:type', Object)], StringArrayRotateFunctionNode.prototype, "stringArray", void 0);
-__decorate([Initializable_1.initializable(), __metadata('design:type', String)], StringArrayRotateFunctionNode.prototype, "stringArrayName", void 0);
-__decorate([Initializable_1.initializable(), __metadata('design:type', Number)], StringArrayRotateFunctionNode.prototype, "stringArrayRotateValue", void 0);
-StringArrayRotateFunctionNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata('design:paramtypes', [Object])], StringArrayRotateFunctionNode);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayRotateFunctionNode.prototype, "stringArray", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayRotateFunctionNode.prototype, "stringArrayName", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Number)], StringArrayRotateFunctionNode.prototype, "stringArrayRotateValue", void 0);
+StringArrayRotateFunctionNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], StringArrayRotateFunctionNode);
 exports.StringArrayRotateFunctionNode = StringArrayRotateFunctionNode;
 
 /***/ },
@@ -5425,7 +5471,7 @@ var class_validator_1 = __webpack_require__(114);
 var DefaultPreset_1 = __webpack_require__(34);
 var OptionsNormalizer_1 = __webpack_require__(83);
 var ValidationErrorsFormatter_1 = __webpack_require__(84);
-var Options = Options_1 = function Options(inputOptions) {
+var Options_1 = function Options(inputOptions) {
     _classCallCheck(this, Options);
 
     Object.assign(this, DefaultPreset_1.DEFAULT_PRESET, inputOptions);
@@ -5435,41 +5481,42 @@ var Options = Options_1 = function Options(inputOptions) {
     }
     Object.assign(this, OptionsNormalizer_1.OptionsNormalizer.normalizeOptions(this));
 };
+var Options = Options_1;
 Options.validatorOptions = {
     validationError: {
         target: false
     }
 };
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "compact", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "controlFlowFlattening", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "debugProtection", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "debugProtectionInterval", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "disableConsoleOutput", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "compact", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "controlFlowFlattening", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "debugProtection", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "debugProtectionInterval", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "disableConsoleOutput", void 0);
 __decorate([class_validator_1.IsArray(), class_validator_1.ArrayUnique(), class_validator_1.IsString({
     each: true
-}), __metadata("design:type", Array)], Options.prototype, "domainLock", void 0);
+}), __metadata('design:type', Array)], Options.prototype, "domainLock", void 0);
 __decorate([class_validator_1.IsArray(), class_validator_1.ArrayUnique(), class_validator_1.IsString({
     each: true
-}), __metadata("design:type", Array)], Options.prototype, "reservedNames", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "rotateStringArray", void 0);
-__decorate([class_validator_1.IsNumber(), __metadata("design:type", Number)], Options.prototype, "seed", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "selfDefending", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "sourceMap", void 0);
+}), __metadata('design:type', Array)], Options.prototype, "reservedNames", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "rotateStringArray", void 0);
+__decorate([class_validator_1.IsNumber(), __metadata('design:type', Number)], Options.prototype, "seed", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "selfDefending", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "sourceMap", void 0);
 __decorate([class_validator_1.IsString(), class_validator_1.ValidateIf(function (options) {
     return Boolean(options.sourceMapBaseUrl);
 }), class_validator_1.IsUrl({
     require_protocol: true,
     require_valid_protocol: true
-}), __metadata("design:type", String)], Options.prototype, "sourceMapBaseUrl", void 0);
-__decorate([class_validator_1.IsString(), __metadata("design:type", String)], Options.prototype, "sourceMapFileName", void 0);
-__decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata("design:type", String)], Options.prototype, "sourceMapMode", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "stringArray", void 0);
-__decorate([class_validator_1.IsIn([true, false, 'base64', 'rc4']), __metadata("design:type", Object)], Options.prototype, "stringArrayEncoding", void 0);
-__decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata("design:type", Number)], Options.prototype, "stringArrayThreshold", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "unicodeEscapeSequence", void 0);
-Options = Options_1 = __decorate([inversify_1.injectable(), __metadata("design:paramtypes", [Object])], Options);
+}), __metadata('design:type', String)], Options.prototype, "sourceMapBaseUrl", void 0);
+__decorate([class_validator_1.IsString(), __metadata('design:type', String)], Options.prototype, "sourceMapFileName", void 0);
+__decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata('design:type', String)], Options.prototype, "sourceMapMode", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "stringArray", void 0);
+__decorate([class_validator_1.IsIn([true, false, 'base64', 'rc4']), __metadata('design:type', Object)], Options.prototype, "stringArrayEncoding", void 0);
+__decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata('design:type', Number)], Options.prototype, "stringArrayThreshold", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "unicodeEscapeSequence", void 0);
+Options = Options_1 = __decorate([inversify_1.injectable(), __metadata('design:paramtypes', [typeof (_a = typeof TInputOptions_1.TInputOptions !== 'undefined' && TInputOptions_1.TInputOptions) === 'function' && _a || Object])], Options);
 exports.Options = Options;
-var Options_1;
+var _a;
 
 /***/ },
 /* 83 */
@@ -5482,6 +5529,15 @@ var _createClass = (function () { function defineProperties(target, props) { for
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var Utils_1 = __webpack_require__(4);
 
 var OptionsNormalizer = function () {
@@ -5492,7 +5548,7 @@ var OptionsNormalizer = function () {
     _createClass(OptionsNormalizer, null, [{
         key: "normalizeOptions",
         value: function normalizeOptions(options) {
-            var normalizedOptions = Object.assign({}, options);
+            var normalizedOptions = __assign({}, options);
             var _iteratorNormalCompletion = true;
             var _didIteratorError = false;
             var _iteratorError = undefined;
@@ -5550,9 +5606,7 @@ var OptionsNormalizer = function () {
                     }
                 }
 
-                Object.assign(options, {
-                    domainLock: normalizedDomains
-                });
+                options = __assign({}, options, { domainLock: normalizedDomains });
             }
             return options;
         }
@@ -5560,36 +5614,34 @@ var OptionsNormalizer = function () {
         key: "selfDefendingRule",
         value: function selfDefendingRule(options) {
             if (options.selfDefending) {
-                Object.assign(options, OptionsNormalizer.SELF_DEFENDING_OPTIONS);
+                options = __assign({}, options, OptionsNormalizer.SELF_DEFENDING_OPTIONS);
             }
             return options;
         }
     }, {
         key: "sourceMapBaseUrlRule",
         value: function sourceMapBaseUrlRule(options) {
-            var sourceMapBaseUrl = options.sourceMapBaseUrl;
+            var _options = options,
+                sourceMapBaseUrl = _options.sourceMapBaseUrl;
+
             if (!options.sourceMapFileName) {
-                Object.assign(options, {
-                    sourceMapBaseUrl: ''
-                });
+                options = __assign({}, options, { sourceMapBaseUrl: '' });
                 return options;
             }
             if (sourceMapBaseUrl && !sourceMapBaseUrl.endsWith('/')) {
-                Object.assign(options, {
-                    sourceMapBaseUrl: sourceMapBaseUrl + "/"
-                });
+                options = __assign({}, options, { sourceMapBaseUrl: sourceMapBaseUrl + "/" });
             }
             return options;
         }
     }, {
         key: "sourceMapFileNameRule",
         value: function sourceMapFileNameRule(options) {
-            var sourceMapFileName = options.sourceMapFileName;
+            var _options2 = options,
+                sourceMapFileName = _options2.sourceMapFileName;
+
             if (sourceMapFileName) {
                 sourceMapFileName = sourceMapFileName.replace(/^\/+/, '').split('.')[0];
-                Object.assign(options, {
-                    sourceMapFileName: sourceMapFileName + ".js.map"
-                });
+                options = __assign({}, options, { sourceMapFileName: sourceMapFileName + ".js.map" });
             }
             return options;
         }
@@ -5597,7 +5649,7 @@ var OptionsNormalizer = function () {
         key: "stringArrayRule",
         value: function stringArrayRule(options) {
             if (!options.stringArray) {
-                Object.assign(options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
+                options = __assign({}, options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
             }
             return options;
         }
@@ -5605,7 +5657,7 @@ var OptionsNormalizer = function () {
         key: "stringArrayEncodingRule",
         value: function stringArrayEncodingRule(options) {
             if (options.stringArrayEncoding === true) {
-                Object.assign(options, OptionsNormalizer.UNICODE_ARRAY_ENCODING_OPTIONS);
+                options = __assign({}, options, OptionsNormalizer.UNICODE_ARRAY_ENCODING_OPTIONS);
             }
             return options;
         }
@@ -5613,7 +5665,7 @@ var OptionsNormalizer = function () {
         key: "stringArrayThresholdRule",
         value: function stringArrayThresholdRule(options) {
             if (options.stringArrayThreshold === 0) {
-                Object.assign(options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
+                options = __assign({}, options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
             }
             return options;
         }
@@ -5718,6 +5770,15 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
+var __assign = undefined && undefined.__assign || Object.assign || function (t) {
+    for (var s, i = 1, n = arguments.length; i < n; i++) {
+        s = arguments[i];
+        for (var p in s) {
+            if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+        }
+    }
+    return t;
+};
 var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
     var c = arguments.length,
         r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
@@ -5740,7 +5801,7 @@ var estraverse = __webpack_require__(6);
 var CalleeDataExtractors_1 = __webpack_require__(31);
 var Node_1 = __webpack_require__(5);
 var NodeUtils_1 = __webpack_require__(10);
-var StackTraceAnalyzer_1 = function () {
+var StackTraceAnalyzer = StackTraceAnalyzer_1 = function () {
     function StackTraceAnalyzer(calleeDataExtractorsFactory) {
         _classCallCheck(this, StackTraceAnalyzer);
 
@@ -5793,9 +5854,7 @@ var StackTraceAnalyzer_1 = function () {
                 if (!calleeData) {
                     return;
                 }
-                stackTraceData.push(Object.assign({}, calleeData, {
-                    stackTrace: _this2.analyzeRecursive(calleeData.callee.body)
-                }));
+                stackTraceData.push(__assign({}, calleeData, { stackTrace: _this2.analyzeRecursive(calleeData.callee.body) }));
             });
         }
     }], [{
@@ -5816,12 +5875,12 @@ var StackTraceAnalyzer_1 = function () {
 
     return StackTraceAnalyzer;
 }();
-var StackTraceAnalyzer = StackTraceAnalyzer_1;
 StackTraceAnalyzer.calleeDataExtractorsList = [CalleeDataExtractors_1.CalleeDataExtractors.FunctionDeclarationCalleeDataExtractor, CalleeDataExtractors_1.CalleeDataExtractors.FunctionExpressionCalleeDataExtractor, CalleeDataExtractors_1.CalleeDataExtractors.ObjectExpressionCalleeDataExtractor];
 StackTraceAnalyzer.limitThresholdActivationLength = 25;
 StackTraceAnalyzer.limitThreshold = 0.002;
-StackTraceAnalyzer = StackTraceAnalyzer_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<ICalleeDataExtractor>'])), __metadata('design:paramtypes', [Function])], StackTraceAnalyzer);
+StackTraceAnalyzer = StackTraceAnalyzer_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<ICalleeDataExtractor>'])), __metadata("design:paramtypes", [Function])], StackTraceAnalyzer);
 exports.StackTraceAnalyzer = StackTraceAnalyzer;
+var StackTraceAnalyzer_1;
 
 /***/ },
 /* 86 */

+ 3 - 4
src/JavaScriptObfuscatorInternal.ts

@@ -66,10 +66,9 @@ export class JavaScriptObfuscatorInternal implements IJavaScriptObfuscator {
      * @param astTree
      */
     private generateCode (sourceCode: string, astTree: ESTree.Program): IGeneratorOutput {
-        const escodegenParams: escodegen.GenerateOptions = Object.assign(
-            {},
-            JavaScriptObfuscatorInternal.escodegenParams
-        );
+        const escodegenParams: escodegen.GenerateOptions = {
+            ...JavaScriptObfuscatorInternal.escodegenParams
+        };
 
         if (this.options.sourceMap) {
             escodegenParams.sourceMap = 'sourceMap';

+ 4 - 1
src/cli/JavaScriptObfuscatorCLI.ts

@@ -136,7 +136,10 @@ export class JavaScriptObfuscatorCLI {
             (<any>inputOptions)[option] = (<any>this.commands)[option];
         }
 
-        return Object.assign({}, DEFAULT_PRESET, inputOptions);
+        return {
+            ...DEFAULT_PRESET,
+            ...inputOptions
+        };
     }
 
     private configureCommands (): void {

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

@@ -59,9 +59,10 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
                 format(SingleNodeCallControllerTemplate(), {
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                 }),
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     seed: this.options.seed
-                })
+                }
             ).getObfuscatedCode();
         }
 

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

@@ -48,9 +48,10 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
                 selfDefendingFunctionName: RandomGeneratorUtils.getRandomVariableName(),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
-            Object.assign({},  NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 seed: this.options.seed
-            })
+            }
         ).getObfuscatedCode();
     }
 }

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

@@ -79,9 +79,10 @@ export class StringArrayCallsWrapper extends AbstractCustomNode implements ICust
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayName: this.stringArrayName
             }),
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 seed: this.options.seed
-            })
+            }
         ).getObfuscatedCode();
     }
 

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

@@ -87,9 +87,10 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
                 stringArrayRotateValue: Utils.decToHex(this.stringArrayRotateValue),
                 whileFunctionName
             }),
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 seed: this.options.seed
-            })
+            }
         ).getObfuscatedCode();
     }
 }

+ 33 - 15
src/options/OptionsNormalizer.ts

@@ -50,7 +50,9 @@ export class OptionsNormalizer {
      * @returns {IOptions}
      */
     public static normalizeOptions (options: IOptions): IOptions {
-        let normalizedOptions: IOptions = Object.assign({}, options);
+        let normalizedOptions: IOptions = {
+            ...options
+        };
 
         for (const normalizerRule of OptionsNormalizer.normalizerRules) {
             normalizedOptions = normalizerRule(normalizedOptions);
@@ -71,9 +73,10 @@ export class OptionsNormalizer {
                 normalizedDomains.push(Utils.extractDomainFromUrl(domain));
             }
 
-            Object.assign(options, {
+            options = {
+                ...options,
                 domainLock: normalizedDomains
-            });
+            };
         }
 
         return options;
@@ -85,7 +88,10 @@ export class OptionsNormalizer {
      */
     private static selfDefendingRule (options: IOptions): IOptions {
         if (options.selfDefending) {
-            Object.assign(options, OptionsNormalizer.SELF_DEFENDING_OPTIONS);
+            options = {
+                ...options,
+                ...OptionsNormalizer.SELF_DEFENDING_OPTIONS
+            };
         }
 
         return options;
@@ -96,20 +102,22 @@ export class OptionsNormalizer {
      * @returns {IOptions}
      */
     private static sourceMapBaseUrlRule (options: IOptions): IOptions {
-        const sourceMapBaseUrl: string = options.sourceMapBaseUrl;
+        const { sourceMapBaseUrl }: { sourceMapBaseUrl: string } = options;
 
         if (!options.sourceMapFileName) {
-            Object.assign(options, {
+            options = {
+                ...options,
                 sourceMapBaseUrl: ''
-            });
+            };
 
             return options;
         }
 
         if (sourceMapBaseUrl && !sourceMapBaseUrl.endsWith('/')) {
-            Object.assign(options, {
+            options = {
+                ...options,
                 sourceMapBaseUrl: `${sourceMapBaseUrl}/`
-            });
+            };
         }
 
         return options;
@@ -120,16 +128,17 @@ export class OptionsNormalizer {
      * @returns {IOptions}
      */
     private static sourceMapFileNameRule (options: IOptions): IOptions {
-        let sourceMapFileName: string = options.sourceMapFileName;
+        let { sourceMapFileName }: { sourceMapFileName: string } = options;
 
         if (sourceMapFileName) {
             sourceMapFileName = sourceMapFileName
                 .replace(/^\/+/, '')
                 .split('.')[0];
 
-            Object.assign(options, {
+            options = {
+                ...options,
                 sourceMapFileName: `${sourceMapFileName}.js.map`
-            });
+            };
         }
 
         return options;
@@ -141,7 +150,10 @@ export class OptionsNormalizer {
      */
     private static stringArrayRule (options: IOptions): IOptions {
         if (!options.stringArray) {
-            Object.assign(options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
+            options = {
+                ...options,
+                ...OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS
+            };
         }
 
         return options;
@@ -153,7 +165,10 @@ export class OptionsNormalizer {
      */
     private static stringArrayEncodingRule (options: IOptions): IOptions {
         if (options.stringArrayEncoding === true) {
-            Object.assign(options, OptionsNormalizer.UNICODE_ARRAY_ENCODING_OPTIONS);
+            options = {
+                ...options,
+                ...OptionsNormalizer.UNICODE_ARRAY_ENCODING_OPTIONS
+            };
         }
 
         return options;
@@ -165,7 +180,10 @@ export class OptionsNormalizer {
      */
     private static stringArrayThresholdRule (options: IOptions): IOptions {
         if (options.stringArrayThreshold === 0) {
-            Object.assign(options, OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS);
+            options = {
+                ...options,
+                ...OptionsNormalizer.DISABLED_UNICODE_ARRAY_OPTIONS
+            };
         }
 
         return options;

+ 4 - 5
src/stack-trace-analyzer/StackTraceAnalyzer.ts

@@ -162,11 +162,10 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer {
                 return;
             }
 
-            stackTraceData.push(
-                Object.assign({}, calleeData, {
-                    stackTrace: this.analyzeRecursive(calleeData.callee.body)
-                })
-            );
+            stackTraceData.push({
+                ...calleeData,
+                stackTrace: this.analyzeRecursive(calleeData.callee.body)
+            });
         });
     }
 }

+ 14 - 12
test/dev/dev.ts

@@ -8,21 +8,23 @@ if (!(<any>global)._babelPolyfill) {
 (function () {
     const JavaScriptObfuscator: any = require("../../index");
 
-    let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(`
-        (function(){
-            function t () {
-                return function () {
-                    var t = 1 * 2;
+    let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
+        `
+            (function(){
+                function t () {
+                    return function () {
+                        var t = 1 * 2;
+                    }
                 }
-            }
-            
-            var s = 1 - 3;
-        })();
-    `,
-        Object.assign({}, NO_CUSTOM_NODES_PRESET,  {
+                
+                var s = 1 - 3;
+            })();
+        `,
+        {
+            ...NO_CUSTOM_NODES_PRESET,
             controlFlowFlattening: true,
             disableConsoleOutput: false
-        })
+        }
     ).getObfuscatedCode();
 
     console.log(obfuscatedCode);

+ 182 - 0
test/fixtures/runtime/sha256.js

@@ -0,0 +1,182 @@
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+/* SHA-256 (FIPS 180-4) implementation in JavaScript                  (c) Chris Veness 2002-2016  */
+/*                                                                                   MIT Licence  */
+/* www.movable-type.co.uk/scripts/sha256.html                                                     */
+/*                                                                                                */
+/*  - see http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html                              */
+/*        http://csrc.nist.gov/groups/ST/toolkit/examples.html                                    */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+'use strict';
+
+
+/**
+ * SHA-256 hash function reference implementation.
+ *
+ * This is a direct implementation of FIPS 180-4, without any optimisations. It is intended to aid
+ * understanding of the algorithm rather than for production use, though it could be used where
+ * performance is not critical.
+ *
+ * @namespace
+ */
+var Sha256 = {};
+
+
+/**
+ * Generates SHA-256 hash of string.
+ *
+ * @param   {string} msg - (Unicode) string to be hashed.
+ * @param   {Object} [options]
+ * @param   {string} [options.msgFormat=string] - Message format: 'string' for JavaScript string
+ *   (gets converted to UTF-8 for hashing); 'hex-bytes' for string of hex bytes ('616263' ≡ 'abc') .
+ * @param   {string} [options.outFormat=hex] - Output format: 'hex' for string of contiguous
+ *   hex bytes; 'hex-w' for grouping hex bytes into groups of (4 byte / 8 character) words.
+ * @returns {string} Hash of msg as hex character string.
+ */
+Sha256.hash = function(msg, options) {
+    var defaults = { msgFormat: 'string', outFormat: 'hex' };
+    var opt = Object.assign(defaults, options);
+
+    // note use throughout this routine of 'n >>> 0' to coerce Number 'n' to unsigned 32-bit integer
+
+    switch (opt.msgFormat) {
+        default: // default is to convert string to UTF-8, as SHA only deals with byte-streams
+        case 'string':   msg = Sha256.utf8Encode(msg);       break;
+        case 'hex-bytes':msg = Sha256.hexBytesToString(msg); break; // mostly for running tests
+    }
+
+    // constants [§4.2.2]
+    var K = [
+        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ];
+
+    // initial hash value [§5.3.3]
+    var H = [
+        0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ];
+
+    // PREPROCESSING [§6.2.1]
+
+    msg += String.fromCharCode(0x80);  // add trailing '1' bit (+ 0's padding) to string [§5.1.1]
+
+    // convert string msg into 512-bit blocks (array of 16 32-bit integers) [§5.2.1]
+    var l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length
+    var N = Math.ceil(l/16);  // number of 16-integer (512-bit) blocks required to hold 'l' ints
+    var M = new Array(N);     // message M is N×16 array of 32-bit integers
+
+    for (var i=0; i<N; i++) {
+        M[i] = new Array(16);
+        for (var j=0; j<16; j++) { // encode 4 chars per integer (64 per block), big-endian encoding
+            M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) |
+                (msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
+        } // note running off the end of msg is ok 'cos bitwise ops on NaN return 0
+    }
+    // add length (in bits) into final pair of 32-bit integers (big-endian) [§5.1.1]
+    // note: most significant word would be (len-1)*8 >>> 32, but since JS converts
+    // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators
+    var lenHi = ((msg.length-1)*8) / Math.pow(2, 32);
+    var lenLo = ((msg.length-1)*8) >>> 0;
+    M[N-1][14] = Math.floor(lenHi);
+    M[N-1][15] = lenLo;
+
+
+    // HASH COMPUTATION [§6.2.2]
+
+    for (var i=0; i<N; i++) {
+        var W = new Array(64);
+
+        // 1 - prepare message schedule 'W'
+        for (var t=0;  t<16; t++) W[t] = M[i][t];
+        for (var t=16; t<64; t++) {
+            W[t] = (Sha256.σ1(W[t-2]) + W[t-7] + Sha256.σ0(W[t-15]) + W[t-16]) >>> 0;
+        }
+
+        // 2 - initialise working variables a, b, c, d, e, f, g, h with previous hash value
+        var a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
+
+        // 3 - main loop (note 'addition modulo 2^32')
+        for (var t=0; t<64; t++) {
+            var T1 = h + Sha256.Σ1(e) + Sha256.Ch(e, f, g) + K[t] + W[t];
+            var T2 =     Sha256.Σ0(a) + Sha256.Maj(a, b, c);
+            h = g;
+            g = f;
+            f = e;
+            e = (d + T1) >>> 0;
+            d = c;
+            c = b;
+            b = a;
+            a = (T1 + T2) >>> 0;
+        }
+
+        // 4 - compute the new intermediate hash value (note '>>> 0' for 'addition modulo 2^32')
+        H[0] = (H[0]+a) >>> 0;
+        H[1] = (H[1]+b) >>> 0;
+        H[2] = (H[2]+c) >>> 0;
+        H[3] = (H[3]+d) >>> 0;
+        H[4] = (H[4]+e) >>> 0;
+        H[5] = (H[5]+f) >>> 0;
+        H[6] = (H[6]+g) >>> 0;
+        H[7] = (H[7]+h) >>> 0;
+    }
+
+    // convert H0..H7 to hex strings (with leading zeros)
+    for (var h=0; h<H.length; h++) H[h] = ('00000000'+H[h].toString(16)).slice(-8);
+
+    // concatenate H0..H7, with separator if required
+    var separator = opt.outFormat=='hex-w' ? ' ' : '';
+
+    return H.join(separator);
+};
+
+
+/**
+ * Rotates right (circular right shift) value x by n positions [§3.2.4].
+ * @private
+ */
+Sha256.ROTR = function(n, x) {
+    return (x >>> n) | (x << (32-n));
+};
+
+/**
+ * Logical functions [§4.1.2].
+ * @private
+ */
+Sha256.Σ0  = function(x) { return Sha256.ROTR(2,  x) ^ Sha256.ROTR(13, x) ^ Sha256.ROTR(22, x); };
+Sha256.Σ1  = function(x) { return Sha256.ROTR(6,  x) ^ Sha256.ROTR(11, x) ^ Sha256.ROTR(25, x); };
+Sha256.σ0  = function(x) { return Sha256.ROTR(7,  x) ^ Sha256.ROTR(18, x) ^ (x>>>3);  };
+Sha256.σ1  = function(x) { return Sha256.ROTR(17, x) ^ Sha256.ROTR(19, x) ^ (x>>>10); };
+Sha256.Ch  = function(x, y, z) { return (x & y) ^ (~x & z); };          // 'choice'
+Sha256.Maj = function(x, y, z) { return (x & y) ^ (x & z) ^ (y & z); }; // 'majority'
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+
+/**
+ * Encodes multi-byte string to utf8 - monsur.hossa.in/2012/07/20/utf-8-in-javascript.html
+ */
+Sha256.utf8Encode = function(str) {
+    return unescape(encodeURIComponent(str));
+};
+
+
+/**
+ * Converts a string of a sequence of hex numbers to a string of characters (eg '616263' => 'abc').
+ */
+Sha256.hexBytesToString = function(hexStr) {
+    hexStr = hexStr.replace(' ', ''); // allow space-separated groups
+    var str = '';
+    for (var i=0; i<hexStr.length; i+=2) {
+        str += String.fromCharCode(parseInt(hexStr.slice(i, i+2), 16));
+    }
+    return str;
+};
+
+function sha256 (string) {
+    return Sha256.hash(string);
+}

+ 23 - 13
test/functional-tests/JavaScriptObfuscator.spec.ts

@@ -1,3 +1,5 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
 
 import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
@@ -5,15 +7,15 @@ import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
 import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
 import { readFileAsString } from '../helpers/readFileAsString';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('JavaScriptObfuscator', () => {
     describe('obfuscate (sourceCode: string, customOptions?: IObfuscatorOptions): IObfuscationResult', () => {
         describe('if `sourceMap` option is `false`', () => {
             it('should returns object with obfuscated code and empty source map', () => {
                 let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     `var test = 1;`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                    {
+                        ...NO_CUSTOM_NODES_PRESET
+                    }
                 );
 
                 assert.isOk(obfuscationResult.getObfuscatedCode());
@@ -25,9 +27,10 @@ describe('JavaScriptObfuscator', () => {
             it('should returns object with obfuscated code and source map', () => {
                 let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     `var test = 1;`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                    {
+                        ...NO_CUSTOM_NODES_PRESET,
                         sourceMap: true
-                    })
+                    }
                 );
 
                 assert.isOk(obfuscationResult.getObfuscatedCode());
@@ -37,10 +40,11 @@ describe('JavaScriptObfuscator', () => {
             it('should returns object with obfuscated code with inline source map as Base64 string', () => {
                 let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                     `var test = 1;`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                    {
+                        ...NO_CUSTOM_NODES_PRESET,
                         sourceMap: true,
                         sourceMapMode: 'inline'
-                    })
+                    }
                 );
 
                 assert.isOk(obfuscationResult.getObfuscatedCode());
@@ -86,7 +90,9 @@ describe('JavaScriptObfuscator', () => {
             assert.match(
                 JavaScriptObfuscator.obfuscate(
                     `var test = 1;`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                    {
+                        ...NO_CUSTOM_NODES_PRESET
+                    }
                 ).getObfuscatedCode(),
                 /^var *test *= *0x\d+;$/
             );
@@ -96,7 +102,9 @@ describe('JavaScriptObfuscator', () => {
             assert.match(
                 JavaScriptObfuscator.obfuscate(
                     `(function () {var test = 1;})()`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                    {
+                        ...NO_CUSTOM_NODES_PRESET
+                    }
                 ).getObfuscatedCode(),
                 /^\(function *\(\) *\{ *var *_0x[\w]+ *= *0x\d+; *\}(\(\)\)|\)\(\));?$/
             );
@@ -107,17 +115,19 @@ describe('JavaScriptObfuscator', () => {
                 pattern2: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/,
                 obfuscatedCode1: string = JavaScriptObfuscator.obfuscate(
                     `var test = 'abc';`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                    {
+                        ...NO_CUSTOM_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
-                    })
+                    }
                 ).getObfuscatedCode(),
                 obfuscatedCode2: string = JavaScriptObfuscator.obfuscate(
                     `var test = 'абц';`,
-                    Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                    {
+                        ...NO_CUSTOM_NODES_PRESET,
                         stringArray: true,
                         stringArrayThreshold: 1
-                    })
+                    }
                 ).getObfuscatedCode();
 
             assert.match(obfuscatedCode1, pattern1);

+ 2 - 2
test/functional-tests/JavaScriptObfuscatorCLI.spec.ts

@@ -2,12 +2,12 @@ import * as fs from 'fs';
 import * as mkdirp from 'mkdirp';
 import * as sinon from 'sinon';
 
+import { assert } from 'chai';
+
 import { StdoutWriteMock } from '../mocks/StdoutWriteMock';
 
 import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('JavaScriptObfuscatorCLI', function (): void {
     let fixturesDirName: string = 'test/fixtures',
         fixtureFileName: string = 'sample.js',

+ 13 - 15
test/functional-tests/JavaScriptObfuscatorInternal.spec.ts

@@ -1,5 +1,7 @@
 import { ServiceIdentifiers } from '../../src/container/ServiceIdentifiers';
 
+import { assert } from 'chai';
+
 import { IInversifyContainerFacade } from '../../src/interfaces/container/IInversifyContainerFacade';
 import { IJavaScriptObfuscator } from '../../src/interfaces/IJavaScriptObfsucator';
 import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
@@ -8,8 +10,6 @@ import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPr
 
 import { InversifyContainerFacade } from '../../src/container/InversifyContainerFacade';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('JavaScriptObfuscatorInternal', () => {
     describe(`setSourceMapUrl (url: string)`, () => {
         let inversifyContainerFacade: IInversifyContainerFacade,
@@ -18,12 +18,11 @@ describe('JavaScriptObfuscatorInternal', () => {
             sourceMapUrl: string = 'test.js.map';
 
         it('should link obfuscated code with source map', () => {
-            inversifyContainerFacade = new InversifyContainerFacade(
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
-                    sourceMap: true,
-                    sourceMapFileName: sourceMapUrl
-                })
-            );
+            inversifyContainerFacade = new InversifyContainerFacade({
+                ...NO_CUSTOM_NODES_PRESET,
+                sourceMap: true,
+                sourceMapFileName: sourceMapUrl
+            });
             javaScriptObfuscator = inversifyContainerFacade
                 .get<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator);
 
@@ -39,13 +38,12 @@ describe('JavaScriptObfuscatorInternal', () => {
         it('should properly add base url to source map import inside obfuscated code if `sourceMapBaseUrl` is set', () => {
             const sourceMapBaseUrl: string = 'http://localhost:9000';
 
-            inversifyContainerFacade = new InversifyContainerFacade(
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
-                    sourceMap: true,
-                    sourceMapBaseUrl: sourceMapBaseUrl,
-                    sourceMapFileName: sourceMapUrl
-                })
-            );
+            inversifyContainerFacade = new InversifyContainerFacade({
+                ...NO_CUSTOM_NODES_PRESET,
+                sourceMap: true,
+                sourceMapBaseUrl: sourceMapBaseUrl,
+                sourceMapFileName: sourceMapUrl
+            });
             javaScriptObfuscator = inversifyContainerFacade
                 .get<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator);
 

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

@@ -1,20 +1,22 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 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}/;
 
     it('should correctly append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 disableConsoleOutput: true
-            })
+
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(), regExp);
@@ -23,10 +25,11 @@ describe('ConsoleOutputDisableExpressionNode', () => {
     it('should\'t append `ConsoleOutputDisableExpressionNode` custom node into the obfuscated code if `disableConsoleOutput` option is not set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 disableConsoleOutput: false,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.notMatch(obfuscationResult.getObfuscatedCode(), regExp);

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

@@ -1,18 +1,19 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('DomainLockNode', () => {
     it('should correctly append `DomainLockNode` custom node into the obfuscated code if `domainLock` option is set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 domainLock: ['.example.com']
-            })
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
@@ -21,9 +22,10 @@ describe('DomainLockNode', () => {
     it('should\'t append `DomainLockNode` custom node into the obfuscated code if `domainLock` option is not set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 domainLock: []
-            })
+            }
         );
 
         assert.notMatch(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);

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

@@ -1,20 +1,21 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('StringArrayCallsWrapper', () => {
     it('should correctly append `StringArrayCallsWrapper` custom node into the obfuscated code', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 stringArray: true,
                 stringArrayThreshold: 1,
                 wrapStringArrayCalls: true
-            })
+            }
         );
 
         assert.match(

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

@@ -1,19 +1,20 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('StringArrayNode', () => {
     it('should correctly append `StringArrayNode` custom node into the obfuscated code if `stringArray` option is set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 stringArray: true,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
@@ -22,9 +23,10 @@ describe('StringArrayNode', () => {
     it('should\'t append `StringArrayNode` custom node into the obfuscated code if `stringArray` option is not set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 stringArray: false
-            })
+            }
         );
 
         assert.notMatch(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);

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

@@ -1,20 +1,21 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('StringArrayRotateFunctionNode', () => {
     it('should correctly append `StringArrayRotateFunctionNode` custom node into the obfuscated code if `rotateStringArray` option is set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 rotateStringArray: true,
                 stringArray: true,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
@@ -23,11 +24,12 @@ describe('StringArrayRotateFunctionNode', () => {
     it('should\'t append `StringArrayRotateFunctionNode` custom node into the obfuscated code if `rotateStringArray` option is not set', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 'test';`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 rotateStringArray: false,
                 stringArray: true,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.notMatch(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);

+ 5 - 3
test/functional-tests/node-transformers/node-obfuscators/CatchClauseObfuscator.spec.ts

@@ -1,3 +1,5 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
@@ -6,15 +8,15 @@ import { readFileAsString } from '../../../helpers/readFileAsString';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('CatchClauseObfuscator', () => {
     describe('changeControlFlow (catchClauseNode: ESTree.CatchClause): void', () => {
         const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             readFileAsString(
                 './test/fixtures/node-transformers/node-obfuscators/catch-clause-obfuscator/catch-clause-obfuscator.js'
             ),
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
         const paramNameRegExp: RegExp = /catch *\((_0x([a-z0-9]){4,6})\) *\{/;

+ 5 - 3
test/functional-tests/node-transformers/node-obfuscators/FunctionDeclarationObfuscator.spec.ts

@@ -1,11 +1,11 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('FunctionDeclarationObfuscator', () => {
     describe('obfuscation of `functionDeclaration` node names', () => {
         const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
@@ -23,7 +23,9 @@ describe('FunctionDeclarationObfuscator', () => {
                     foo();
                 }
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 

+ 18 - 16
test/functional-tests/node-transformers/node-obfuscators/FunctionObfuscator.spec.ts

@@ -1,30 +1,32 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('FunctionObfuscator', () => {
     describe('identifiers obfuscation inside `FunctionDeclaration` and `FunctionExpression` node body', () => {
         const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `
-                    (function () {
-                        var test = function (test) {
-                            console.log(test);
-                            
-                            if (true) {
-                                var test = 5
-                            }
-                            
-                            variable = 6;
-                            
-                            return test;
+                (function () {
+                    var test = function (test) {
+                        console.log(test);
+                        
+                        if (true) {
+                            var test = 5
                         }
-                    })();
-                `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                        
+                        variable = 6;
+                        
+                        return test;
+                    }
+                })();
+            `,
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
 

+ 5 - 3
test/functional-tests/node-transformers/node-obfuscators/LabeledStatementObfuscator.spec.ts

@@ -1,3 +1,5 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
@@ -6,15 +8,15 @@ import { readFileAsString } from '../../../helpers/readFileAsString';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('LabeledStatementObfuscator', () => {
     describe('changeControlFlow (labeledStatementNode: ESTree.LabeledStatement): void', () => {
         const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             readFileAsString(
                 './test/fixtures/node-transformers/node-obfuscators/labeled-statement-obfuscator/labeled-statement-obfuscator.js'
             ),
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
         const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
         const labeledStatementRegExp: RegExp = /(_0x([a-z0-9]){4,6}): *\{/;

+ 26 - 17
test/functional-tests/node-transformers/node-obfuscators/LiteralObfuscator.spec.ts

@@ -1,17 +1,19 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('LiteralObfuscator', () => {
     describe('obfuscation of literal node with string value', () => {
         it('should replace literal node value with unicode escape sequence', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'test';`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /^var *test *= *'\\x74\\x65\\x73\\x74';$/);
@@ -20,10 +22,11 @@ describe('LiteralObfuscator', () => {
         it('should replace literal node value with unicode escape sequence from unicode array', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'test';`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
-                })
+                }
             );
 
             assert.match(
@@ -36,11 +39,12 @@ describe('LiteralObfuscator', () => {
         it('should replace literal node value with raw value from unicode array if `unicodeEscapeSequence` is disabled', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'test';`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1,
                     unicodeEscapeSequence: false
-                })
+                }
             );
 
             assert.match(
@@ -53,10 +57,11 @@ describe('LiteralObfuscator', () => {
         it('shouldn\'t replace short literal node value with unicode array value', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'te';`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
-                })
+                }
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *'\\x74\\x65';/);
@@ -65,11 +70,12 @@ describe('LiteralObfuscator', () => {
         it('should replace literal node value with unicode array value encoded using base64', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'test';`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayEncoding: 'base64',
                     stringArrayThreshold: 1
-                })
+                }
             );
 
             assert.match(
@@ -82,11 +88,12 @@ describe('LiteralObfuscator', () => {
         it('should replace literal node value with unicode array value encoded using rc4', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'test';`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayEncoding: 'rc4',
                     stringArrayThreshold: 1
-                })
+                }
             );
 
             assert.match(
@@ -99,10 +106,11 @@ describe('LiteralObfuscator', () => {
     it('should obfuscate literal node with boolean value', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = true;`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 stringArray: true,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /^var *test *= *!!\[\];$/);
@@ -111,10 +119,11 @@ describe('LiteralObfuscator', () => {
     it('should obfuscate literal node with number value', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = 0;`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 stringArray: true,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /^var *test *= *0x0;$/);

+ 14 - 8
test/functional-tests/node-transformers/node-obfuscators/MemberExpressionObfuscator.spec.ts

@@ -1,17 +1,19 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('MemberExpressionObfuscator', () => {
     describe('obfuscation of member expression node with dot notation', () => {
         it('should replace member expression dot notation call by square brackets call with unicode literal value', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = console.log;`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\['\\x6c\\x6f\\x67'\];/);
@@ -20,10 +22,11 @@ describe('MemberExpressionObfuscator', () => {
         it('should replace member expression dot notation call by square brackets call to unicode array', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = console.log;`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
-                })
+                }
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
@@ -35,10 +38,11 @@ describe('MemberExpressionObfuscator', () => {
         it('should replace member expression square brackets call by square brackets call to unicode array', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = console['log'];`,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
                     stringArray: true,
                     stringArrayThreshold: 1
-                })
+                }
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
@@ -51,7 +55,9 @@ describe('MemberExpressionObfuscator', () => {
                     var identifier = 'log'; 
                     var test = console[identifier];
                 `,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *console\[identifier\];/);

+ 11 - 6
test/functional-tests/node-transformers/node-obfuscators/MethodDefinitionObfuscator.spec.ts

@@ -1,11 +1,11 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('MethodDefinitionObfuscator', () => {
     let code: string = `
         class Foo {
@@ -17,7 +17,9 @@ describe('MethodDefinitionObfuscator', () => {
     it('should replace method definition node `key` property with unicode value', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             code,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /\['\\x62\\x61\\x72'\]\(\)\{\}/);
@@ -26,10 +28,11 @@ describe('MethodDefinitionObfuscator', () => {
     it('should replace method definition node `key` property with unicode array call', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             code,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET, {
+            {
+                ...NO_CUSTOM_NODES_PRESET,
                 stringArray: true,
                 stringArrayThreshold: 1
-            })
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4} *= *\['\\x62\\x61\\x72'\];/);
@@ -39,7 +42,9 @@ describe('MethodDefinitionObfuscator', () => {
     it('should not obfuscate method definition node with `constructor` key', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             code,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /constructor\(\)\{\}/);

+ 14 - 6
test/functional-tests/node-transformers/node-obfuscators/ObjectExpressionObfuscator.spec.ts

@@ -1,16 +1,18 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('ObjectExpressionObfuscator', () => {
     it('should replace object expression node `key` property with literal value by unicode value', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = { 'foo': 0 };`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
@@ -19,7 +21,9 @@ describe('ObjectExpressionObfuscator', () => {
     it('should replace object expression node `key` property with identifier value by unicode value', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             `var test = { foo: 0 };`,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
@@ -34,7 +38,9 @@ describe('ObjectExpressionObfuscator', () => {
                     var test = {a, b};
                 })();
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(
@@ -52,7 +58,9 @@ describe('ObjectExpressionObfuscator', () => {
                     var test = {a, b};
                 })();
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(

+ 45 - 29
test/functional-tests/node-transformers/node-obfuscators/VariableDeclarationObfuscator.spec.ts

@@ -1,11 +1,11 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResult';
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/preset-options/NoCustomNodesPreset';
 
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('VariableDeclarationObfuscator', () => {
     it('should obfuscate `variableDeclaration` node', () => {
         let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
@@ -15,7 +15,9 @@ describe('VariableDeclarationObfuscator', () => {
                     console.log(test);
                 }
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *_0x([a-z0-9]){4,6} *= *'\\x61\\x62\\x63';/);
@@ -31,7 +33,9 @@ describe('VariableDeclarationObfuscator', () => {
         
                 console.log(test);
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *0xa;/);
@@ -49,7 +53,9 @@ describe('VariableDeclarationObfuscator', () => {
                     console.log(test);
                 })();
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
@@ -66,7 +72,9 @@ describe('VariableDeclarationObfuscator', () => {
                     console.log(test);
                 })();
             `,
-            Object.assign({}, NO_CUSTOM_NODES_PRESET)
+            {
+                ...NO_CUSTOM_NODES_PRESET
+            }
         );
 
         assert.match(obfuscationResult.getObfuscatedCode(),  /console\['\\x6c\\x6f\\x67'\]\(test\);/);
@@ -91,7 +99,9 @@ describe('VariableDeclarationObfuscator', () => {
                         bar();
                     }
                 `,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
             );
         });
 
@@ -128,7 +138,9 @@ describe('VariableDeclarationObfuscator', () => {
                         }
                     })();
                 `,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
+                {
+                    ...NO_CUSTOM_NODES_PRESET
+                }
             );
         });
 
@@ -166,17 +178,19 @@ describe('VariableDeclarationObfuscator', () => {
         it('shouldn\'t replace property node identifier', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `
-                function foo () {
-                    var test = 'abc';
-                    
-                    var object = {
-                        test: 'cde'
-                    };
-                    
-                    console.log(test);
+                    function foo () {
+                        var test = 'abc';
+                        
+                        var object = {
+                            test: 'cde'
+                        };
+                        
+                        console.log(test);
+                    }
+                `,
+                {
+                    ...NO_CUSTOM_NODES_PRESET
                 }
-            `,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /var _0x([a-z0-9]){4,6} *= *\{'\\x74\\x65\\x73\\x74/);
@@ -185,18 +199,20 @@ describe('VariableDeclarationObfuscator', () => {
         it('shouldn\'t replace computed member expression identifier', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `
-                function foo () {
-                    var test = 'abc';
-                    
-                    var object = {
-                        'test': 'cde'
-                    };
-                    
-                    console.log(test);
-                    console.log(object.test);
+                    function foo () {
+                        var test = 'abc';
+                        
+                        var object = {
+                            'test': 'cde'
+                        };
+                        
+                        console.log(test);
+                        console.log(object.test);
+                    }
+                `,
+                {
+                    ...NO_CUSTOM_NODES_PRESET
                 }
-            `,
-                Object.assign({}, NO_CUSTOM_NODES_PRESET)
             );
 
             assert.match(obfuscationResult.getObfuscatedCode(),  /_0x([a-z0-9]){4,6}\['\\x74\\x65\\x73\\x74'\]/);

+ 2 - 3
test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts

@@ -1,9 +1,10 @@
 import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
 
-import * as chai from 'chai';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
+import { assert } from 'chai';
+
 import { TNodeWithBlockStatement } from '../../../src/types/node/TNodeWithBlockStatement';
 
 import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
@@ -17,8 +18,6 @@ import { Node } from '../../../src/node/Node';
 import { NodeMocks } from '../../mocks/NodeMocks';
 import { NodeUtils } from '../../../src/node/NodeUtils';
 
-const assert: any = chai.assert;
-
 /**
  * @param astTree
  * @param name

+ 2 - 3
test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts

@@ -1,12 +1,11 @@
 import * as format from 'string-template';
 
+import { assert } from 'chai';
+
 import { DomainLockNodeTemplate } from '../../../../../src/templates/custom-nodes/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
 
 import { CryptUtils } from '../../../../../src/utils/CryptUtils';
 
-
-const assert: Chai.AssertStatic = require('chai').assert;
-
 /**
  * @param templateData
  * @param callsControllerFunctionName

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

@@ -1,5 +1,7 @@
 import * as format from 'string-template';
 
+import { assert } from 'chai';
+
 import { AtobTemplate } from '../../../../../src/templates/custom-nodes/AtobTemplate';
 import { Rc4Template } from '../../../../../src/templates/custom-nodes/Rc4Template';
 import { StringArrayBase64DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate';
@@ -8,8 +10,6 @@ import { StringArrayRc4DecodeNodeTemplate } from '../../../../../src/templates/c
 
 import { CryptUtils } from '../../../../../src/utils/CryptUtils';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 /**
  * @param templateData
  * @param stringArrayName

+ 5 - 0
test/index.spec.ts

@@ -48,3 +48,8 @@ import './functional-tests/templates/custom-nodes/string-array-nodes/StringArray
  * Performance tests
  */
 import './performance-tests/JavaScriptObfuscatorPerformance.spec';
+
+/**
+ * Runtime tests
+ */
+import './runtime-tests/JavaScriptObfuscatorRuntime.spec';

+ 2 - 2
test/performance-tests/JavaScriptObfuscatorPerformance.spec.ts

@@ -1,9 +1,9 @@
+import { assert } from 'chai';
+
 import { readFileAsString } from '../helpers/readFileAsString';
 
 import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('JavaScriptObfuscator performance', () => {
     const iterationsCount: number = 500;
 

+ 28 - 0
test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts

@@ -0,0 +1,28 @@
+import { assert } from 'chai';
+
+import { readFileAsString } from '../helpers/readFileAsString';
+
+import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
+
+import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
+
+describe('JavaScriptObfuscator runtime eval', () => {
+    it('should obfuscate code without any runtime errors after obfuscation: variant #1 sha256', () => {
+        const code: string = readFileAsString('./test/fixtures/runtime/sha256.js');
+
+        const obfuscationResult1: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+            code,
+            {
+                selfDefending: true,
+                debugProtection: true,
+                stringArrayEncoding: 'rc4',
+                controlFlowFlattening: true
+            }
+        );
+
+        assert.equal(
+            eval(`${obfuscationResult1.getObfuscatedCode()} sha256('test');`),
+            '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
+        );
+    });
+});

+ 2 - 2
test/unit-tests/ObfuscationResult.spec.ts

@@ -1,9 +1,9 @@
+import { assert } from 'chai';
+
 import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
 
 import { ObfuscationResult } from '../../src/ObfuscationResult';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('ObfuscationResult', () => {
     describe('constructor (obfuscatedCode: string, sourceMap: string)', () => {
         let obfuscatedCode: string = 'obfuscatedCode',

+ 53 - 37
test/unit-tests/OptionsNormalizer.spec.ts

@@ -1,3 +1,5 @@
+import { assert } from 'chai';
+
 import { TInputOptions } from '../../src/types/options/TInputOptions';
 
 import { IOptions } from '../../src/interfaces/options/IOptions';
@@ -7,8 +9,6 @@ import { DEFAULT_PRESET } from '../../src/preset-options/DefaultPreset';
 import { Options } from '../../src/options/Options';
 import { OptionsNormalizer } from '../../src/options/OptionsNormalizer';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 /**
  * @param optionsPreset
  * @returns {IOptions}
@@ -25,113 +25,129 @@ describe('OptionsNormalizer', () => {
             expectedOptionsPreset: TInputOptions;
 
         it('should normalize options preset: domainLockRule', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 domainLock: ['//localhost:9000', 'https://google.ru/abc?cde=fgh']
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 domainLock: ['localhost', 'google.ru']
-            });
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: selfDefendingRule', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 selfDefending: true,
                 compact: false
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 selfDefending: true,
                 compact: true
-            });
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: sourceMapBaseUrlRule #1', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 sourceMapBaseUrl: 'http://localhost:9000',
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
-                sourceMapBaseUrl: '',
-            });
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
+                sourceMapBaseUrl: ''
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: sourceMapBaseUrlRule #2', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 sourceMapBaseUrl: 'http://localhost:9000',
                 sourceMapFileName: '/outputSourceMapName.map'
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 sourceMapBaseUrl: 'http://localhost:9000/',
                 sourceMapFileName: 'outputSourceMapName.js.map'
-            });
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: sourceMapFileNameRule', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 sourceMapBaseUrl: 'http://localhost:9000',
-                sourceMapFileName: '//outputSourceMapName',
-            });
+                sourceMapFileName: '//outputSourceMapName'
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 sourceMapBaseUrl: 'http://localhost:9000/',
-                sourceMapFileName: 'outputSourceMapName.js.map',
-            });
+                sourceMapFileName: 'outputSourceMapName.js.map'
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: stringArrayRule', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 stringArray: false,
                 stringArrayEncoding: 'rc4',
                 stringArrayThreshold: 0.5,
                 rotateStringArray: true
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 stringArray: false,
                 stringArrayEncoding: false,
                 stringArrayThreshold: 0,
                 rotateStringArray: false
-            });
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: stringArrayEncodingRule', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 stringArrayEncoding: true
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 stringArrayEncoding: 'base64'
-            });
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });
 
         it('should normalize options preset: stringArrayThresholdRule', () => {
-            optionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            optionsPreset = {
+                ...DEFAULT_PRESET,
                 rotateStringArray: true,
                 stringArray: true,
                 stringArrayThreshold: 0
-            });
+            };
 
-            expectedOptionsPreset = Object.assign({}, DEFAULT_PRESET, {
+            expectedOptionsPreset = {
+                ...DEFAULT_PRESET,
                 rotateStringArray: false,
                 stringArray: false,
                 stringArrayThreshold: 0
-            });
+            };
 
             assert.deepEqual(getNormalizedOptions(optionsPreset), expectedOptionsPreset);
         });

+ 2 - 2
test/unit-tests/SourceMapCorrector.spec.ts

@@ -1,5 +1,7 @@
 import { ServiceIdentifiers } from '../../src/container/ServiceIdentifiers';
 
+import { assert } from 'chai';
+
 import { TSourceMapMode } from '../../src/types/TSourceMapMode';
 
 import { IInversifyContainerFacade } from '../../src/interfaces/container/IInversifyContainerFacade';
@@ -10,8 +12,6 @@ import { SourceMapMode } from '../../src/enums/SourceMapMode';
 
 import { InversifyContainerFacade } from '../../src/container/InversifyContainerFacade';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 /**
  * @param obfuscatedCode
  * @param sourceMap

+ 2 - 2
test/unit-tests/cli/CLIUtils.spec.ts

@@ -1,9 +1,9 @@
 import * as fs from 'fs';
 import * as mkdirp from 'mkdirp';
 
-import { CLIUtils } from '../../../src/cli/CLIUtils';
+import { assert } from 'chai';
 
-const assert: Chai.AssertStatic = require('chai').assert;
+import { CLIUtils } from '../../../src/cli/CLIUtils';
 
 describe('CLIUtils', () => {
     const fileContent: string = 'test',

+ 2 - 2
test/unit-tests/decorators/Initializable.spec.ts

@@ -1,8 +1,8 @@
+import { assert } from 'chai';
+
 import { initializable } from '../../../src/decorators/Initializable';
 import { IInitializable } from '../../../src/interfaces/IInitializable';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('@initializable', () => {
     describe('initializable (initializeMethodKey: string): any', () => {
         it('shouldn\'t throws an errors if property was initialized', () => {

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

@@ -1,8 +1,9 @@
 import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
 
-import * as chai from 'chai';
 import * as ESTree from 'estree';
 
+import { assert } from 'chai';
+
 import { TStatement } from '../../../src/types/node/TStatement';
 
 import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
@@ -16,8 +17,6 @@ import { NodeAppender } from '../../../src/node/NodeAppender';
 import { NodeMocks } from '../../mocks/NodeMocks';
 import { NodeUtils } from '../../../src/node/NodeUtils';
 
-const assert: any = chai.assert;
-
 describe('NodeAppender', () => {
     describe('appendNode (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[]): void', () => {
         let astTree: ESTree.Program,

+ 2 - 3
test/unit-tests/node/NodeUtils.spec.ts

@@ -1,11 +1,10 @@
-import * as chai from 'chai';
 import * as ESTree from 'estree';
 
+import { assert } from 'chai';
+
 import { NodeMocks } from '../../mocks/NodeMocks';
 import { NodeUtils } from '../../../src/node/NodeUtils';
 
-const assert: any = chai.assert;
-
 describe('NodeUtils', () => {
     describe('addXVerbatimPropertyToLiterals (node: ESTree.Node): void', () => {
         let literalNode: any,

+ 1 - 3
test/unit-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts

@@ -1,9 +1,7 @@
-import * as chai from 'chai';
+import { assert } from 'chai';
 
 import { StackTraceAnalyzer } from '../../../src/stack-trace-analyzer/StackTraceAnalyzer';
 
-const assert: any = chai.assert;
-
 describe('StackTraceAnalyzer', () => {
     describe('getLimitIndex (blockScopeBodyLength: number): number', () => {
         it('should returns correct limit index based on block scope body length', () => {

+ 2 - 2
test/unit-tests/storages/ControlFlowStorage.spec.ts

@@ -1,6 +1,8 @@
 /*
 import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
 
+ import { assert } from 'chai';
+
 import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
 import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
 import { IStorage } from '../../../src/interfaces/storages/IStorage';
@@ -9,8 +11,6 @@ import { CustomNodes } from '../../../src/enums/container/CustomNodes';
 
 import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('ControlFlowStorage', () => {
     describe('toString (): string', () => {
         it('should returns obfuscated code if `.toString()` was called on `ObfuscationResult` object', () => {

+ 2 - 2
test/unit-tests/utils/CryptUtils.spec.ts

@@ -1,6 +1,6 @@
-import { CryptUtils } from '../../../src/utils/CryptUtils';
+import { assert } from 'chai';
 
-const assert: Chai.AssertStatic = require('chai').assert;
+import { CryptUtils } from '../../../src/utils/CryptUtils';
 
 describe('CryptUtils', () => {
     describe('btoa (string: string): string', () => {

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

@@ -1,6 +1,6 @@
-import { RandomGeneratorUtils } from '../../../src/utils/RandomGeneratorUtils';
+import { assert } from 'chai';
 
-const assert: Chai.AssertStatic = require('chai').assert;
+import { RandomGeneratorUtils } from '../../../src/utils/RandomGeneratorUtils';
 
 describe('RandomGeneratorUtils', () => {
     describe('getRandomVariableName (length: number = 6): string', () => {

+ 2 - 2
test/unit-tests/utils/Utils.spec.ts

@@ -1,9 +1,9 @@
+import { assert } from 'chai';
+
 import { Utils } from '../../../src/utils/Utils';
 
 import { JSFuck } from '../../../src/enums/JSFuck';
 
-const assert: Chai.AssertStatic = require('chai').assert;
-
 describe('Utils', () => {
     describe('arrayContains (array: any[], searchElement: any): boolean', () => {
         it('should return boolean depends on condition if array is contains given value or not', () => {