From 0bb94a3674d332bb24a1ea8484079f980221b693 Mon Sep 17 00:00:00 2001 From: sanex3339 Date: Wed, 23 Nov 2016 19:02:34 +0300 Subject: [PATCH] refactoring --- dist/index.js | 387 ++++++++++-------- src/JavaScriptObfuscator.ts | 10 +- src/JavaScriptObfuscatorInternal.ts | 54 +-- src/Obfuscator.ts | 170 +++----- src/SourceMapCorrector.ts | 8 +- src/enums/VisitorDirection.ts | 6 + src/interfaces/INodeTransformersFactory.d.ts | 5 + src/interfaces/IObfuscator.d.ts | 2 +- .../IStackTraceAnalyzer.d.ts | 4 +- .../NodeControlFlowTransformersFactory.ts | 57 +++ .../NodeObfuscatorsFactory.ts | 76 ++++ .../StackTraceAnalyzer.ts | 17 +- src/types/TVisitorDirection.d.ts | 1 + .../JavaScriptObfuscatorInternal.spec.ts | 34 +- .../StackTraceAnalyzer.spec.ts | 23 +- test/unit-tests/node/NodeAppender.spec.ts | 13 +- 16 files changed, 506 insertions(+), 361 deletions(-) create mode 100644 src/enums/VisitorDirection.ts create mode 100644 src/interfaces/INodeTransformersFactory.d.ts create mode 100644 src/node-transformers/NodeControlFlowTransformersFactory.ts create mode 100644 src/node-transformers/NodeObfuscatorsFactory.ts create mode 100644 src/types/TVisitorDirection.d.ts diff --git a/dist/index.js b/dist/index.js index c7739484..f8b49adc 100644 --- a/dist/index.js +++ b/dist/index.js @@ -88,7 +88,7 @@ module.exports = /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 102); +/******/ return __webpack_require__(__webpack_require__.s = 101); /******/ }) /************************************************************************/ /******/ ([ @@ -106,7 +106,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var chance_1 = __webpack_require__(24); var JSFuck_1 = __webpack_require__(21); -var isEqual = __webpack_require__(99); +var isEqual = __webpack_require__(98); var Utils = function () { function Utils() { @@ -909,6 +909,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var JavaScriptObfuscatorCLI_1 = __webpack_require__(32); var JavaScriptObfuscatorInternal_1 = __webpack_require__(28); +var Options_1 = __webpack_require__(63); var JavaScriptObfuscator = function () { function JavaScriptObfuscator() { @@ -920,9 +921,8 @@ var JavaScriptObfuscator = function () { value: function obfuscate(sourceCode) { var obfuscatorOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var javaScriptObfuscator = new JavaScriptObfuscatorInternal_1.JavaScriptObfuscatorInternal(sourceCode, obfuscatorOptions); - javaScriptObfuscator.obfuscate(); - return javaScriptObfuscator.getObfuscationResult(); + var javaScriptObfuscator = new JavaScriptObfuscatorInternal_1.JavaScriptObfuscatorInternal(new Options_1.Options(obfuscatorOptions)); + return javaScriptObfuscator.obfuscate(sourceCode); } }, { key: 'runCLI', @@ -1117,7 +1117,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var SingleNodeCallControllerTemplate_1 = __webpack_require__(77); +var SingleNodeCallControllerTemplate_1 = __webpack_require__(76); var NoCustomNodesPreset_1 = __webpack_require__(16); var AbstractCustomNode_1 = __webpack_require__(5); var JavaScriptObfuscator_1 = __webpack_require__(10); @@ -1488,36 +1488,31 @@ var escodegen = __webpack_require__(11); var chance_1 = __webpack_require__(24); var ObfuscationResult_1 = __webpack_require__(20); var Obfuscator_1 = __webpack_require__(29); -var Options_1 = __webpack_require__(63); var SourceMapCorrector_1 = __webpack_require__(30); var Utils_1 = __webpack_require__(0); var JavaScriptObfuscatorInternal = function () { - function JavaScriptObfuscatorInternal(sourceCode) { - var obfuscatorOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - + function JavaScriptObfuscatorInternal(options) { _classCallCheck(this, JavaScriptObfuscatorInternal); - this.sourceCode = sourceCode; - this.options = new Options_1.Options(obfuscatorOptions); + this.options = options; } _createClass(JavaScriptObfuscatorInternal, [{ key: 'getObfuscationResult', - value: function getObfuscationResult() { - return new SourceMapCorrector_1.SourceMapCorrector(new ObfuscationResult_1.ObfuscationResult(this.generatorOutput.code, this.generatorOutput.map), this.options.sourceMapBaseUrl + this.options.sourceMapFileName, this.options.sourceMapMode).correct(); + value: function getObfuscationResult(generatorOutput) { + return new SourceMapCorrector_1.SourceMapCorrector(new ObfuscationResult_1.ObfuscationResult(generatorOutput.code, generatorOutput.map), this.options.sourceMapBaseUrl + this.options.sourceMapFileName, this.options.sourceMapMode).correct(); } }, { key: 'obfuscate', - value: function obfuscate() { - var astTree = esprima.parse(this.sourceCode, { - loc: true - }); + value: function obfuscate(sourceCode) { if (this.options.seed !== 0) { Utils_1.Utils.setRandomGenerator(new chance_1.Chance(this.options.seed)); } - astTree = new Obfuscator_1.Obfuscator(this.options).obfuscateNode(astTree); - this.generatorOutput = JavaScriptObfuscatorInternal.generateCode(this.sourceCode, astTree, this.options); + var astTree = esprima.parse(sourceCode, JavaScriptObfuscatorInternal.esprimaParams); + var obfuscatedAstTree = new Obfuscator_1.Obfuscator(this.options).obfuscateAstTree(astTree); + var generatorOutput = JavaScriptObfuscatorInternal.generateCode(sourceCode, obfuscatedAstTree, this.options); + return this.getObfuscationResult(generatorOutput); } }], [{ key: 'generateCode', @@ -1543,6 +1538,9 @@ JavaScriptObfuscatorInternal.escodegenParams = { verbatim: 'x-verbatim-property', sourceMapWithCode: true }; +JavaScriptObfuscatorInternal.esprimaParams = { + loc: true +}; exports.JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal; /***/ }, @@ -1554,69 +1552,64 @@ exports.JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var estraverse = __webpack_require__(4); var AppendState_1 = __webpack_require__(1); -var NodeType_1 = __webpack_require__(7); -var CatchClauseObfuscator_1 = __webpack_require__(53); +var VisitorDirection_1 = __webpack_require__(104); var ConsoleOutputNodesGroup_1 = __webpack_require__(45); var DebugProtectionNodesGroup_1 = __webpack_require__(46); var DomainLockNodesGroup_1 = __webpack_require__(47); -var FunctionDeclarationObfuscator_1 = __webpack_require__(54); -var FunctionObfuscator_1 = __webpack_require__(55); -var LabeledStatementObfuscator_1 = __webpack_require__(56); -var LiteralObfuscator_1 = __webpack_require__(57); -var MemberExpressionObfuscator_1 = __webpack_require__(58); -var MethodDefinitionObfuscator_1 = __webpack_require__(59); var Node_1 = __webpack_require__(2); +var NodeControlFlowTransformersFactory_1 = __webpack_require__(103); +var NodeObfuscatorsFactory_1 = __webpack_require__(102); var NodeUtils_1 = __webpack_require__(8); -var ObjectExpressionObfuscator_1 = __webpack_require__(60); var SelfDefendingNodesGroup_1 = __webpack_require__(48); var StackTraceAnalyzer_1 = __webpack_require__(66); var StringArrayNodesGroup_1 = __webpack_require__(49); -var VariableDeclarationObfuscator_1 = __webpack_require__(61); -var FunctionControlFlowTransformer_1 = __webpack_require__(50); var Obfuscator = function () { function Obfuscator(options) { _classCallCheck(this, Obfuscator); - this.customNodes = new Map(); this.options = options; } _createClass(Obfuscator, [{ - key: 'obfuscateNode', - value: function obfuscateNode(node) { - if (Node_1.Node.isProgramNode(node) && !node.body.length) { - return node; + key: 'obfuscateAstTree', + value: function obfuscateAstTree(astTree) { + if (Node_1.Node.isProgramNode(astTree) && !astTree.body.length) { + return astTree; } - NodeUtils_1.NodeUtils.parentize(node); - var stackTraceData = new StackTraceAnalyzer_1.StackTraceAnalyzer(node.body).analyze(); - this.initializeCustomNodes(stackTraceData); - this.beforeObfuscation(node); - this.obfuscate(node); - this.afterObfuscation(node); - return node; + NodeUtils_1.NodeUtils.parentize(astTree); + this.initializeCustomNodes(new StackTraceAnalyzer_1.StackTraceAnalyzer().analyze(astTree.body)); + this.beforeTransform(astTree); + if (this.options.controlFlowFlattening) { + this.transformAstTree(astTree, VisitorDirection_1.VisitorDirection.leave, new NodeControlFlowTransformersFactory_1.NodeControlFlowTransformersFactory(this.customNodes, this.options)); + } + this.transformAstTree(astTree, VisitorDirection_1.VisitorDirection.enter, new NodeObfuscatorsFactory_1.NodeObfuscatorsFactory(this.customNodes, this.options)); + this.afterTransform(astTree); + return astTree; } }, { - key: 'afterObfuscation', - value: function afterObfuscation(astTree) { - this.customNodes.forEach(function (node) { - if (node.getAppendState() === AppendState_1.AppendState.AfterObfuscation) { - node.appendNode(astTree); + key: 'afterTransform', + value: function afterTransform(astTree) { + this.customNodes.forEach(function (customNode) { + if (customNode.getAppendState() === AppendState_1.AppendState.AfterObfuscation) { + customNode.appendNode(astTree); } }); } }, { - key: 'beforeObfuscation', - value: function beforeObfuscation(astTree) { - this.customNodes.forEach(function (node) { - if (node.getAppendState() === AppendState_1.AppendState.BeforeObfuscation) { - node.appendNode(astTree); + key: 'beforeTransform', + value: function beforeTransform(astTree) { + this.customNodes.forEach(function (customNode) { + if (customNode.getAppendState() === AppendState_1.AppendState.BeforeObfuscation) { + customNode.appendNode(astTree); } }); } @@ -1636,54 +1629,21 @@ var Obfuscator = function () { this.customNodes = new Map(customNodes); } }, { - key: 'initializeNodeControlFlowChangers', - value: function initializeNodeControlFlowChangers(node, parentNode) { - this.initializeNodeTransformers(node, parentNode, Obfuscator.nodeControlFlowChangers); - } - }, { - key: 'initializeNodeObfuscators', - value: function initializeNodeObfuscators(node, parentNode) { - this.initializeNodeTransformers(node, parentNode, Obfuscator.nodeObfuscators); - } - }, { - key: 'initializeNodeTransformers', - value: function initializeNodeTransformers(node, parentNode, nodeTransformersMap) { - var _this2 = this; - - var nodeTransformers = nodeTransformersMap.get(node.type); - if (!nodeTransformers) { - return; - } - nodeTransformers.forEach(function (transformer) { - new transformer(_this2.customNodes, _this2.options).transformNode(node, parentNode); - }); - } - }, { - key: 'obfuscate', - value: function obfuscate(node) { - var _this3 = this; - - if (this.options.controlFlowFlattening) { - estraverse.traverse(node, { - leave: function leave(node, parentNode) { - _this3.initializeNodeControlFlowChangers(node, parentNode); - } + key: 'transformAstTree', + value: function transformAstTree(astTree, direction, nodeTransformersFactory) { + estraverse.traverse(astTree, _defineProperty({}, direction, function (node, parentNode) { + var nodeTransformers = nodeTransformersFactory.initializeNodeTransformers(node.type); + nodeTransformers.forEach(function (nodeTransformer) { + nodeTransformer.transformNode(node, parentNode); }); - } - estraverse.traverse(node, { - enter: function enter(node, parentNode) { - _this3.initializeNodeObfuscators(node, parentNode); - } - }); + })); } }]); return Obfuscator; }(); -Obfuscator.nodeControlFlowChangers = new Map([[NodeType_1.NodeType.FunctionDeclaration, [FunctionControlFlowTransformer_1.FunctionControlFlowTransformer]], [NodeType_1.NodeType.FunctionExpression, [FunctionControlFlowTransformer_1.FunctionControlFlowTransformer]]]); Obfuscator.nodeGroups = [DomainLockNodesGroup_1.DomainLockNodesGroup, SelfDefendingNodesGroup_1.SelfDefendingNodesGroup, ConsoleOutputNodesGroup_1.ConsoleOutputNodesGroup, DebugProtectionNodesGroup_1.DebugProtectionNodesGroup, StringArrayNodesGroup_1.StringArrayNodesGroup]; -Obfuscator.nodeObfuscators = new Map([[NodeType_1.NodeType.ArrowFunctionExpression, [FunctionObfuscator_1.FunctionObfuscator]], [NodeType_1.NodeType.ClassDeclaration, [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator]], [NodeType_1.NodeType.CatchClause, [CatchClauseObfuscator_1.CatchClauseObfuscator]], [NodeType_1.NodeType.FunctionDeclaration, [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator, FunctionObfuscator_1.FunctionObfuscator]], [NodeType_1.NodeType.FunctionExpression, [FunctionObfuscator_1.FunctionObfuscator]], [NodeType_1.NodeType.MemberExpression, [MemberExpressionObfuscator_1.MemberExpressionObfuscator]], [NodeType_1.NodeType.MethodDefinition, [MethodDefinitionObfuscator_1.MethodDefinitionObfuscator]], [NodeType_1.NodeType.ObjectExpression, [ObjectExpressionObfuscator_1.ObjectExpressionObfuscator]], [NodeType_1.NodeType.VariableDeclaration, [VariableDeclarationObfuscator_1.VariableDeclarationObfuscator]], [NodeType_1.NodeType.LabeledStatement, [LabeledStatementObfuscator_1.LabeledStatementObfuscator]], [NodeType_1.NodeType.Literal, [LiteralObfuscator_1.LiteralObfuscator]]]); exports.Obfuscator = Obfuscator; /***/ }, @@ -1755,8 +1715,8 @@ 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 fs = __webpack_require__(98); -var mkdirp = __webpack_require__(100); +var fs = __webpack_require__(97); +var mkdirp = __webpack_require__(99); var path = __webpack_require__(26); var Utils_1 = __webpack_require__(0); @@ -1847,7 +1807,7 @@ 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 commander = __webpack_require__(97); +var commander = __webpack_require__(96); var path = __webpack_require__(26); var SourceMapMode_1 = __webpack_require__(14); var StringArrayEncoding_1 = __webpack_require__(18); @@ -2001,7 +1961,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var ConsoleOutputDisableExpressionTemplate_1 = __webpack_require__(78); +var ConsoleOutputDisableExpressionTemplate_1 = __webpack_require__(77); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); var Utils_1 = __webpack_require__(0); @@ -2058,7 +2018,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var BinaryExpressionFunctionTemplate_1 = __webpack_require__(79); +var BinaryExpressionFunctionTemplate_1 = __webpack_require__(78); var AbstractCustomNode_1 = __webpack_require__(5); var Utils_1 = __webpack_require__(0); @@ -2110,7 +2070,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var ControlFlowStorageCallTemplate_1 = __webpack_require__(80); +var ControlFlowStorageCallTemplate_1 = __webpack_require__(79); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); @@ -2169,7 +2129,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var ControlFlowStorageTemplate_1 = __webpack_require__(81); +var ControlFlowStorageTemplate_1 = __webpack_require__(80); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); @@ -2224,7 +2184,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var DebufProtectionFunctionCallTemplate_1 = __webpack_require__(82); +var DebufProtectionFunctionCallTemplate_1 = __webpack_require__(81); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); @@ -2277,7 +2237,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var DebugProtectionFunctionIntervalTemplate_1 = __webpack_require__(83); +var DebugProtectionFunctionIntervalTemplate_1 = __webpack_require__(82); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); @@ -2330,7 +2290,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var DebugProtectionFunctionTemplate_1 = __webpack_require__(84); +var DebugProtectionFunctionTemplate_1 = __webpack_require__(83); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); var Utils_1 = __webpack_require__(0); @@ -2388,7 +2348,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var DomainLockNodeTemplate_1 = __webpack_require__(85); +var DomainLockNodeTemplate_1 = __webpack_require__(84); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); var Utils_1 = __webpack_require__(0); @@ -2453,7 +2413,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); var NoCustomNodesPreset_1 = __webpack_require__(16); -var SelfDefendingTemplate_1 = __webpack_require__(86); +var SelfDefendingTemplate_1 = __webpack_require__(85); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); var JavaScriptObfuscator_1 = __webpack_require__(10); @@ -2517,12 +2477,12 @@ var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); var StringArrayEncoding_1 = __webpack_require__(18); var NoCustomNodesPreset_1 = __webpack_require__(16); -var AtobTemplate_1 = __webpack_require__(75); -var Rc4Template_1 = __webpack_require__(76); -var SelfDefendingTemplate_1 = __webpack_require__(87); -var StringArrayBase64DecodeNodeTemplate_1 = __webpack_require__(88); -var StringArrayCallsWrapperTemplate_1 = __webpack_require__(89); -var StringArrayRC4DecodeNodeTemplate_1 = __webpack_require__(90); +var AtobTemplate_1 = __webpack_require__(74); +var Rc4Template_1 = __webpack_require__(75); +var SelfDefendingTemplate_1 = __webpack_require__(86); +var StringArrayBase64DecodeNodeTemplate_1 = __webpack_require__(87); +var StringArrayCallsWrapperTemplate_1 = __webpack_require__(88); +var StringArrayRC4DecodeNodeTemplate_1 = __webpack_require__(89); var AbstractCustomNode_1 = __webpack_require__(5); var JavaScriptObfuscator_1 = __webpack_require__(10); var NodeAppender_1 = __webpack_require__(3); @@ -2628,7 +2588,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); -var StringArrayTemplate_1 = __webpack_require__(91); +var StringArrayTemplate_1 = __webpack_require__(90); var AbstractCustomNode_1 = __webpack_require__(5); var NodeAppender_1 = __webpack_require__(3); @@ -2703,8 +2663,8 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var format = __webpack_require__(6); var AppendState_1 = __webpack_require__(1); var NoCustomNodesPreset_1 = __webpack_require__(16); -var SelfDefendingTemplate_1 = __webpack_require__(92); -var StringArrayRotateFunctionTemplate_1 = __webpack_require__(93); +var SelfDefendingTemplate_1 = __webpack_require__(91); +var StringArrayRotateFunctionTemplate_1 = __webpack_require__(92); var AbstractCustomNode_1 = __webpack_require__(5); var JavaScriptObfuscator_1 = __webpack_require__(10); var NodeAppender_1 = __webpack_require__(3); @@ -2979,7 +2939,7 @@ var StringArrayCallsWrapper_1 = __webpack_require__(42); var StringArrayNode_1 = __webpack_require__(43); var StringArrayRotateFunctionNode_1 = __webpack_require__(44); var AbstractNodesGroup_1 = __webpack_require__(12); -var StringArrayStorage_1 = __webpack_require__(74); +var StringArrayStorage_1 = __webpack_require__(73); var Utils_1 = __webpack_require__(0); var StringArrayNodesGroup = function (_AbstractNodesGroup_) { @@ -3041,7 +3001,7 @@ var estraverse = __webpack_require__(4); var NodeType_1 = __webpack_require__(7); var AbstractNodeTransformer_1 = __webpack_require__(9); var BinaryExpressionControlFlowReplacer_1 = __webpack_require__(52); -var ControlFlowStorage_1 = __webpack_require__(73); +var ControlFlowStorage_1 = __webpack_require__(72); var ControlFlowStorageNode_1 = __webpack_require__(36); var Node_1 = __webpack_require__(2); var NodeAppender_1 = __webpack_require__(3); @@ -3919,9 +3879,9 @@ var __decorate = undefined && undefined.__decorate || function (decorators, targ var __metadata = undefined && undefined.__metadata || function (k, v) { if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; -var class_validator_1 = __webpack_require__(96); -var TSourceMapMode_1 = __webpack_require__(94); -var TStringArrayEncoding_1 = __webpack_require__(95); +var class_validator_1 = __webpack_require__(95); +var TSourceMapMode_1 = __webpack_require__(93); +var TStringArrayEncoding_1 = __webpack_require__(94); var DefaultPreset_1 = __webpack_require__(23); var OptionsNormalizer_1 = __webpack_require__(64); var ValidationErrorsFormatter_1 = __webpack_require__(65); @@ -4226,17 +4186,16 @@ var Node_1 = __webpack_require__(2); var NodeUtils_1 = __webpack_require__(8); var StackTraceAnalyzer = function () { - function StackTraceAnalyzer(blockScopeBody) { + function StackTraceAnalyzer() { _classCallCheck(this, StackTraceAnalyzer); this.calleeDataExtractors = new Map([[NodeType_1.NodeType.FunctionDeclaration, FunctionDeclarationCalleeDataExtractor_1.FunctionDeclarationCalleeDataExtractor], [NodeType_1.NodeType.FunctionExpression, FunctionExpressionCalleeDataExtractor_1.FunctionExpressionCalleeDataExtractor], [NodeType_1.NodeType.ObjectExpression, ObjectExpressionCalleeDataExtractor_1.ObjectExpressionCalleeDataExtractor]]); - this.blockScopeBody = blockScopeBody; } _createClass(StackTraceAnalyzer, [{ key: 'analyze', - value: function analyze() { - return this.analyzeRecursive(this.blockScopeBody); + value: function analyze(blockScopeBody) { + return this.analyzeRecursive(blockScopeBody); } }, { key: 'analyzeRecursive', @@ -4553,8 +4512,7 @@ var ObjectExpressionCalleeDataExtractor = function () { exports.ObjectExpressionCalleeDataExtractor = ObjectExpressionCalleeDataExtractor; /***/ }, -/* 70 */, -/* 71 */ +/* 70 */ /***/ function(module, exports) { "use strict"; @@ -4608,7 +4566,7 @@ var ArrayStorage = function () { exports.ArrayStorage = ArrayStorage; /***/ }, -/* 72 */ +/* 71 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -4664,7 +4622,7 @@ var MapStorage = function () { exports.MapStorage = MapStorage; /***/ }, -/* 73 */ +/* 72 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -4680,7 +4638,7 @@ 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 MapStorage_1 = __webpack_require__(72); +var MapStorage_1 = __webpack_require__(71); var ControlFlowStorage = function (_MapStorage_1$MapStor) { _inherits(ControlFlowStorage, _MapStorage_1$MapStor); @@ -4711,7 +4669,7 @@ var ControlFlowStorage = function (_MapStorage_1$MapStor) { exports.ControlFlowStorage = ControlFlowStorage; /***/ }, -/* 74 */ +/* 73 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -4725,7 +4683,7 @@ 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 ArrayStorage_1 = __webpack_require__(71); +var ArrayStorage_1 = __webpack_require__(70); var Utils_1 = __webpack_require__(0); var StringArrayStorage = function (_ArrayStorage_1$Array) { @@ -4757,7 +4715,7 @@ var StringArrayStorage = function (_ArrayStorage_1$Array) { exports.StringArrayStorage = StringArrayStorage; /***/ }, -/* 75 */ +/* 74 */ /***/ function(module, exports) { "use strict"; @@ -4769,7 +4727,7 @@ function AtobTemplate() { exports.AtobTemplate = AtobTemplate; /***/ }, -/* 76 */ +/* 75 */ /***/ function(module, exports) { "use strict"; @@ -4781,7 +4739,7 @@ function Rc4Template() { exports.Rc4Template = Rc4Template; /***/ }, -/* 77 */ +/* 76 */ /***/ function(module, exports) { "use strict"; @@ -4793,7 +4751,7 @@ function SingleNodeCallControllerTemplate() { exports.SingleNodeCallControllerTemplate = SingleNodeCallControllerTemplate; /***/ }, -/* 78 */ +/* 77 */ /***/ function(module, exports) { "use strict"; @@ -4805,7 +4763,7 @@ function ConsoleOutputDisableExpressionTemplate() { exports.ConsoleOutputDisableExpressionTemplate = ConsoleOutputDisableExpressionTemplate; /***/ }, -/* 79 */ +/* 78 */ /***/ function(module, exports) { "use strict"; @@ -4817,7 +4775,7 @@ function BinaryExpressionFunctionTemplate() { exports.BinaryExpressionFunctionTemplate = BinaryExpressionFunctionTemplate; /***/ }, -/* 80 */ +/* 79 */ /***/ function(module, exports) { "use strict"; @@ -4829,7 +4787,7 @@ function ControlFlowStorageCallTemplate() { exports.ControlFlowStorageCallTemplate = ControlFlowStorageCallTemplate; /***/ }, -/* 81 */ +/* 80 */ /***/ function(module, exports) { "use strict"; @@ -4841,7 +4799,7 @@ function ControlFlowStorageTemplate() { exports.ControlFlowStorageTemplate = ControlFlowStorageTemplate; /***/ }, -/* 82 */ +/* 81 */ /***/ function(module, exports) { "use strict"; @@ -4853,7 +4811,7 @@ function DebugProtectionFunctionCallTemplate() { exports.DebugProtectionFunctionCallTemplate = DebugProtectionFunctionCallTemplate; /***/ }, -/* 83 */ +/* 82 */ /***/ function(module, exports) { "use strict"; @@ -4865,7 +4823,7 @@ function DebugProtectionFunctionIntervalTemplate() { exports.DebugProtectionFunctionIntervalTemplate = DebugProtectionFunctionIntervalTemplate; /***/ }, -/* 84 */ +/* 83 */ /***/ function(module, exports) { "use strict"; @@ -4877,7 +4835,7 @@ function DebugProtectionFunctionTemplate() { exports.DebugProtectionFunctionTemplate = DebugProtectionFunctionTemplate; /***/ }, -/* 85 */ +/* 84 */ /***/ function(module, exports) { "use strict"; @@ -4889,7 +4847,7 @@ function DomainLockNodeTemplate() { exports.DomainLockNodeTemplate = DomainLockNodeTemplate; /***/ }, -/* 86 */ +/* 85 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -4902,7 +4860,7 @@ function SelfDefendingTemplate() { exports.SelfDefendingTemplate = SelfDefendingTemplate; /***/ }, -/* 87 */ +/* 86 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -4915,7 +4873,7 @@ function SelfDefendingTemplate() { exports.SelfDefendingTemplate = SelfDefendingTemplate; /***/ }, -/* 88 */ +/* 87 */ /***/ function(module, exports) { "use strict"; @@ -4927,7 +4885,7 @@ function StringArrayBase64DecodeNodeTemplate() { exports.StringArrayBase64DecodeNodeTemplate = StringArrayBase64DecodeNodeTemplate; /***/ }, -/* 89 */ +/* 88 */ /***/ function(module, exports) { "use strict"; @@ -4939,7 +4897,7 @@ function StringArrayCallsWrapperTemplate() { exports.StringArrayCallsWrapperTemplate = StringArrayCallsWrapperTemplate; /***/ }, -/* 90 */ +/* 89 */ /***/ function(module, exports) { "use strict"; @@ -4951,7 +4909,7 @@ function StringArrayRc4DecodeNodeTemplate() { exports.StringArrayRc4DecodeNodeTemplate = StringArrayRc4DecodeNodeTemplate; /***/ }, -/* 91 */ +/* 90 */ /***/ function(module, exports) { "use strict"; @@ -4963,7 +4921,7 @@ function StringArrayTemplate() { exports.StringArrayTemplate = StringArrayTemplate; /***/ }, -/* 92 */ +/* 91 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -4976,7 +4934,7 @@ function SelfDefendingTemplate() { exports.SelfDefendingTemplate = SelfDefendingTemplate; /***/ }, -/* 93 */ +/* 92 */ /***/ function(module, exports) { "use strict"; @@ -4987,6 +4945,13 @@ function StringArrayRotateFunctionTemplate() { } exports.StringArrayRotateFunctionTemplate = StringArrayRotateFunctionTemplate; +/***/ }, +/* 93 */ +/***/ function(module, exports) { + +"use strict"; +"use strict"; + /***/ }, /* 94 */ /***/ function(module, exports) { @@ -4998,42 +4963,35 @@ exports.StringArrayRotateFunctionTemplate = StringArrayRotateFunctionTemplate; /* 95 */ /***/ function(module, exports) { -"use strict"; -"use strict"; +module.exports = require("class-validator"); /***/ }, /* 96 */ /***/ function(module, exports) { -module.exports = require("class-validator"); +module.exports = require("commander"); /***/ }, /* 97 */ /***/ function(module, exports) { -module.exports = require("commander"); +module.exports = require("fs"); /***/ }, /* 98 */ /***/ function(module, exports) { -module.exports = require("fs"); +module.exports = require("is-equal"); /***/ }, /* 99 */ /***/ function(module, exports) { -module.exports = require("is-equal"); - -/***/ }, -/* 100 */ -/***/ function(module, exports) { - module.exports = require("mkdirp"); /***/ }, -/* 101 */, -/* 102 */ +/* 100 */, +/* 101 */ /***/ function(module, exports, __webpack_require__) { "use strict"; @@ -5045,6 +5003,111 @@ if (!global._babelPolyfill) { } module.exports = JavaScriptObfuscator_1.JavaScriptObfuscator; +/***/ }, +/* 102 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var NodeType_1 = __webpack_require__(7); +var CatchClauseObfuscator_1 = __webpack_require__(53); +var FunctionDeclarationObfuscator_1 = __webpack_require__(54); +var FunctionObfuscator_1 = __webpack_require__(55); +var LabeledStatementObfuscator_1 = __webpack_require__(56); +var LiteralObfuscator_1 = __webpack_require__(57); +var MemberExpressionObfuscator_1 = __webpack_require__(58); +var MethodDefinitionObfuscator_1 = __webpack_require__(59); +var ObjectExpressionObfuscator_1 = __webpack_require__(60); +var VariableDeclarationObfuscator_1 = __webpack_require__(61); + +var NodeObfuscatorsFactory = function () { + function NodeObfuscatorsFactory(customNodes, options) { + _classCallCheck(this, NodeObfuscatorsFactory); + + this.customNodes = customNodes; + this.options = options; + } + + _createClass(NodeObfuscatorsFactory, [{ + key: 'initializeNodeTransformers', + value: function initializeNodeTransformers(nodeType) { + var _this = this; + + var nodeObfuscators = NodeObfuscatorsFactory.nodeObfuscators.get(nodeType) || []; + var instancesArray = []; + nodeObfuscators.forEach(function (transformer) { + instancesArray.push(new transformer(_this.customNodes, _this.options)); + }); + return instancesArray; + } + }]); + + return NodeObfuscatorsFactory; +}(); + +NodeObfuscatorsFactory.nodeObfuscators = new Map([[NodeType_1.NodeType.ArrowFunctionExpression, [FunctionObfuscator_1.FunctionObfuscator]], [NodeType_1.NodeType.ClassDeclaration, [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator]], [NodeType_1.NodeType.CatchClause, [CatchClauseObfuscator_1.CatchClauseObfuscator]], [NodeType_1.NodeType.FunctionDeclaration, [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator, FunctionObfuscator_1.FunctionObfuscator]], [NodeType_1.NodeType.FunctionExpression, [FunctionObfuscator_1.FunctionObfuscator]], [NodeType_1.NodeType.MemberExpression, [MemberExpressionObfuscator_1.MemberExpressionObfuscator]], [NodeType_1.NodeType.MethodDefinition, [MethodDefinitionObfuscator_1.MethodDefinitionObfuscator]], [NodeType_1.NodeType.ObjectExpression, [ObjectExpressionObfuscator_1.ObjectExpressionObfuscator]], [NodeType_1.NodeType.VariableDeclaration, [VariableDeclarationObfuscator_1.VariableDeclarationObfuscator]], [NodeType_1.NodeType.LabeledStatement, [LabeledStatementObfuscator_1.LabeledStatementObfuscator]], [NodeType_1.NodeType.Literal, [LiteralObfuscator_1.LiteralObfuscator]]]); +exports.NodeObfuscatorsFactory = NodeObfuscatorsFactory; + +/***/ }, +/* 103 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var NodeType_1 = __webpack_require__(7); +var FunctionControlFlowTransformer_1 = __webpack_require__(50); + +var NodeControlFlowTransformersFactory = function () { + function NodeControlFlowTransformersFactory(customNodes, options) { + _classCallCheck(this, NodeControlFlowTransformersFactory); + + this.customNodes = customNodes; + this.options = options; + } + + _createClass(NodeControlFlowTransformersFactory, [{ + key: 'initializeNodeTransformers', + value: function initializeNodeTransformers(nodeType) { + var _this = this; + + var nodeObfuscators = NodeControlFlowTransformersFactory.nodeControlFlowChangers.get(nodeType) || []; + var instancesArray = []; + nodeObfuscators.forEach(function (transformer) { + instancesArray.push(new transformer(_this.customNodes, _this.options)); + }); + return instancesArray; + } + }]); + + return NodeControlFlowTransformersFactory; +}(); + +NodeControlFlowTransformersFactory.nodeControlFlowChangers = new Map([[NodeType_1.NodeType.FunctionDeclaration, [FunctionControlFlowTransformer_1.FunctionControlFlowTransformer]], [NodeType_1.NodeType.FunctionExpression, [FunctionControlFlowTransformer_1.FunctionControlFlowTransformer]]]); +exports.NodeControlFlowTransformersFactory = NodeControlFlowTransformersFactory; + +/***/ }, +/* 104 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; +"use strict"; + +var Utils_1 = __webpack_require__(0); +exports.VisitorDirection = Utils_1.Utils.strEnumify({ + enter: 'enter', + leave: 'leave' +}); + /***/ } /******/ ]); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/src/JavaScriptObfuscator.ts b/src/JavaScriptObfuscator.ts index 561e4d6b..c4354131 100644 --- a/src/JavaScriptObfuscator.ts +++ b/src/JavaScriptObfuscator.ts @@ -3,6 +3,7 @@ import { IObfuscatorOptions } from './interfaces/IObfuscatorOptions'; import { JavaScriptObfuscatorCLI } from './cli/JavaScriptObfuscatorCLI'; import { JavaScriptObfuscatorInternal } from './JavaScriptObfuscatorInternal'; +import { Options } from './options/Options'; export class JavaScriptObfuscator { /** @@ -11,14 +12,11 @@ export class JavaScriptObfuscator { * @returns {string} */ public static obfuscate (sourceCode: string, obfuscatorOptions: IObfuscatorOptions = {}): IObfuscationResult { - let javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal( - sourceCode, - obfuscatorOptions + const javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal( + new Options(obfuscatorOptions) ); - javaScriptObfuscator.obfuscate(); - - return javaScriptObfuscator.getObfuscationResult(); + return javaScriptObfuscator.obfuscate(sourceCode); } /** diff --git a/src/JavaScriptObfuscatorInternal.ts b/src/JavaScriptObfuscatorInternal.ts index 216ff93a..a98f991d 100644 --- a/src/JavaScriptObfuscatorInternal.ts +++ b/src/JavaScriptObfuscatorInternal.ts @@ -4,14 +4,12 @@ import * as ESTree from 'estree'; import { Chance } from 'chance'; -import { IObfuscatorOptions } from './interfaces/IObfuscatorOptions'; import { IGeneratorOutput } from './interfaces/IGeneratorOutput'; import { IObfuscationResult } from './interfaces/IObfuscationResult'; import { IOptions } from './interfaces/IOptions'; import { ObfuscationResult } from './ObfuscationResult'; import { Obfuscator } from './Obfuscator'; -import { Options } from './options/Options'; import { SourceMapCorrector } from './SourceMapCorrector'; import { Utils } from './Utils'; @@ -19,33 +17,28 @@ export class JavaScriptObfuscatorInternal { /** * @type {GenerateOptions} */ - private static escodegenParams: escodegen.GenerateOptions = { + private static readonly escodegenParams: escodegen.GenerateOptions = { verbatim: 'x-verbatim-property', sourceMapWithCode: true }; /** - * @type {IGeneratorOutput} + * @type {esprima.Options} */ - private generatorOutput: IGeneratorOutput; + private static readonly esprimaParams: esprima.Options = { + loc: true + }; /** * @type {IOptions} */ - private options: IOptions; + private readonly options: IOptions; /** - * @type {string} + * @param options */ - private sourceCode: string; - - /** - * @param sourceCode - * @param obfuscatorOptions - */ - constructor (sourceCode: string, obfuscatorOptions: IObfuscatorOptions = {}) { - this.sourceCode = sourceCode; - this.options = new Options(obfuscatorOptions); + constructor (options: IOptions) { + this.options = options; } /** @@ -53,7 +46,7 @@ export class JavaScriptObfuscatorInternal { * @param astTree * @param options */ - private static generateCode (sourceCode: string, astTree: ESTree.Node, options: IOptions): IGeneratorOutput { + private static generateCode (sourceCode: string, astTree: ESTree.Program, options: IOptions): IGeneratorOutput { const escodegenParams: escodegen.GenerateOptions = Object.assign( {}, JavaScriptObfuscatorInternal.escodegenParams @@ -76,30 +69,37 @@ export class JavaScriptObfuscatorInternal { } /** + * @param generatorOutput * @returns {IObfuscationResult} */ - public getObfuscationResult (): IObfuscationResult { + public getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult { return new SourceMapCorrector( new ObfuscationResult( - this.generatorOutput.code, - this.generatorOutput.map + generatorOutput.code, + generatorOutput.map ), this.options.sourceMapBaseUrl + this.options.sourceMapFileName, this.options.sourceMapMode ).correct(); } - public obfuscate (): void { - let astTree: ESTree.Node = esprima.parse(this.sourceCode, { - loc: true - }); - + /** + * @param sourceCode + * @returns {IObfuscationResult} + */ + public obfuscate (sourceCode: string): IObfuscationResult { if (this.options.seed !== 0) { Utils.setRandomGenerator(new Chance(this.options.seed)); } - astTree = new Obfuscator(this.options).obfuscateNode(astTree); + const astTree: ESTree.Program = esprima.parse(sourceCode, JavaScriptObfuscatorInternal.esprimaParams); + const obfuscatedAstTree: ESTree.Program = new Obfuscator(this.options).obfuscateAstTree(astTree); + const generatorOutput: IGeneratorOutput = JavaScriptObfuscatorInternal.generateCode( + sourceCode, + obfuscatedAstTree, + this.options + ); - this.generatorOutput = JavaScriptObfuscatorInternal.generateCode(this.sourceCode, astTree, this.options); + return this.getObfuscationResult(generatorOutput); } } diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index 66e1cc95..9b308ad2 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -2,48 +2,34 @@ import * as estraverse from 'estraverse'; import * as ESTree from 'estree'; import { TNodeGroup } from './types/TNodeGroup'; -import { TNodeTransformer } from './types/TNodeTransformer'; +import { TVisitorDirection } from './types/TVisitorDirection'; import { ICustomNode } from './interfaces/custom-nodes/ICustomNode'; import { IObfuscator } from './interfaces/IObfuscator'; import { IOptions } from './interfaces/IOptions'; +import { INodeTransformer } from './interfaces/INodeTransformer'; +import { INodeTransformersFactory } from './interfaces/INodeTransformersFactory'; import { IStackTraceData } from './interfaces/stack-trace-analyzer/IStackTraceData'; import { AppendState } from './enums/AppendState'; -import { NodeType } from './enums/NodeType'; +import { VisitorDirection } from './enums/VisitorDirection'; -import { CatchClauseObfuscator } from './node-transformers/node-obfuscators/CatchClauseObfuscator'; import { ConsoleOutputNodesGroup } from './node-groups/ConsoleOutputNodesGroup'; import { DebugProtectionNodesGroup } from './node-groups/DebugProtectionNodesGroup'; import { DomainLockNodesGroup } from './node-groups/DomainLockNodesGroup'; -import { FunctionDeclarationObfuscator } from './node-transformers/node-obfuscators/FunctionDeclarationObfuscator'; -import { FunctionObfuscator } from './node-transformers/node-obfuscators/FunctionObfuscator'; -import { LabeledStatementObfuscator } from './node-transformers/node-obfuscators/LabeledStatementObfuscator'; -import { LiteralObfuscator } from './node-transformers/node-obfuscators/LiteralObfuscator'; -import { MemberExpressionObfuscator } from './node-transformers/node-obfuscators/MemberExpressionObfuscator'; -import { MethodDefinitionObfuscator } from './node-transformers/node-obfuscators/MethodDefinitionObfuscator'; import { Node } from './node/Node'; +import { NodeControlFlowTransformersFactory } from './node-transformers/NodeControlFlowTransformersFactory'; +import { NodeObfuscatorsFactory } from './node-transformers/NodeObfuscatorsFactory'; import { NodeUtils } from './node/NodeUtils'; -import { ObjectExpressionObfuscator } from './node-transformers/node-obfuscators/ObjectExpressionObfuscator'; import { SelfDefendingNodesGroup } from './node-groups/SelfDefendingNodesGroup'; import { StackTraceAnalyzer } from './stack-trace-analyzer/StackTraceAnalyzer'; import { StringArrayNodesGroup } from './node-groups/StringArrayNodesGroup'; -import { VariableDeclarationObfuscator } from './node-transformers/node-obfuscators/VariableDeclarationObfuscator'; -import { FunctionControlFlowTransformer } from './node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer'; export class Obfuscator implements IObfuscator { - /** - * @type {Map} - */ - private static nodeControlFlowChangers: Map = new Map ([ - [NodeType.FunctionDeclaration, [FunctionControlFlowTransformer]], - [NodeType.FunctionExpression, [FunctionControlFlowTransformer]] - ]); - /** * @type {TNodeGroup[]} */ - private static nodeGroups: TNodeGroup[] = [ + private static readonly nodeGroups: TNodeGroup[] = [ DomainLockNodesGroup, SelfDefendingNodesGroup, ConsoleOutputNodesGroup, @@ -51,35 +37,15 @@ export class Obfuscator implements IObfuscator { StringArrayNodesGroup ]; - /** - * @type {Map} - */ - private static nodeObfuscators: Map = new Map ([ - [NodeType.ArrowFunctionExpression, [FunctionObfuscator]], - [NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]], - [NodeType.CatchClause, [CatchClauseObfuscator]], - [NodeType.FunctionDeclaration, [ - FunctionDeclarationObfuscator, - FunctionObfuscator - ]], - [NodeType.FunctionExpression, [FunctionObfuscator]], - [NodeType.MemberExpression, [MemberExpressionObfuscator]], - [NodeType.MethodDefinition, [MethodDefinitionObfuscator]], - [NodeType.ObjectExpression, [ObjectExpressionObfuscator]], - [NodeType.VariableDeclaration, [VariableDeclarationObfuscator]], - [NodeType.LabeledStatement, [LabeledStatementObfuscator]], - [NodeType.Literal, [LiteralObfuscator]] - ]); - /** * @type {Map} */ - private customNodes: Map = new Map (); + private customNodes: Map ; /** * @type {IOptions} */ - private options: IOptions; + private readonly options: IOptions; /** * @param options @@ -89,34 +55,47 @@ export class Obfuscator implements IObfuscator { } /** - * @param node - * @returns {ESTree.Node} + * @param astTree + * @returns {ESTree.Program} */ - public obfuscateNode (node: ESTree.Program): ESTree.Node { - if (Node.isProgramNode(node) && !node.body.length) { - return node; + public obfuscateAstTree (astTree: ESTree.Program): ESTree.Program { + if (Node.isProgramNode(astTree) && !astTree.body.length) { + return astTree; } - NodeUtils.parentize(node); + NodeUtils.parentize(astTree); + this.initializeCustomNodes(new StackTraceAnalyzer().analyze(astTree.body)); - const stackTraceData: IStackTraceData[] = new StackTraceAnalyzer(node.body).analyze(); + // tasks before nodes transformation + this.beforeTransform(astTree); - this.initializeCustomNodes(stackTraceData); + // first pass: control flow flattening + if (this.options.controlFlowFlattening) { + this.transformAstTree(astTree, VisitorDirection.leave, new NodeControlFlowTransformersFactory( + this.customNodes, + this.options + )); + } - this.beforeObfuscation(node); - this.obfuscate(node); - this.afterObfuscation(node); + // second pass: nodes obfuscation + this.transformAstTree(astTree, VisitorDirection.enter, new NodeObfuscatorsFactory( + this.customNodes, + this.options + )); - return node; + // tasks after nodes transformation + this.afterTransform(astTree); + + return astTree; } /** * @param astTree */ - private afterObfuscation (astTree: ESTree.Node): void { - this.customNodes.forEach((node: ICustomNode) => { - if (node.getAppendState() === AppendState.AfterObfuscation) { - node.appendNode(astTree); + private afterTransform (astTree: ESTree.Program): void { + this.customNodes.forEach((customNode: ICustomNode) => { + if (customNode.getAppendState() === AppendState.AfterObfuscation) { + customNode.appendNode(astTree); } }); } @@ -124,10 +103,10 @@ export class Obfuscator implements IObfuscator { /** * @param astTree */ - private beforeObfuscation (astTree: ESTree.Node): void { - this.customNodes.forEach((node: ICustomNode) => { - if (node.getAppendState() === AppendState.BeforeObfuscation) { - node.appendNode(astTree); + private beforeTransform (astTree: ESTree.Program): void { + this.customNodes.forEach((customNode: ICustomNode) => { + if (customNode.getAppendState() === AppendState.BeforeObfuscation) { + customNode.appendNode(astTree); } }); }; @@ -136,7 +115,7 @@ export class Obfuscator implements IObfuscator { * @param stackTraceData */ private initializeCustomNodes (stackTraceData: IStackTraceData[]): void { - let customNodes: [string, ICustomNode][] = []; + const customNodes: [string, ICustomNode][] = []; Obfuscator.nodeGroups.forEach((nodeGroupConstructor: TNodeGroup) => { const nodeGroupNodes: Map | undefined = new nodeGroupConstructor( @@ -154,59 +133,22 @@ export class Obfuscator implements IObfuscator { } /** - * @param node - * @param parentNode + * @param astTree + * @param direction + * @param nodeTransformersFactory */ - private initializeNodeControlFlowChangers (node: ESTree.Node, parentNode: ESTree.Node): void { - this.initializeNodeTransformers(node, parentNode, Obfuscator.nodeControlFlowChangers); - } - - /** - * @param node - * @param parentNode - */ - private initializeNodeObfuscators (node: ESTree.Node, parentNode: ESTree.Node): void { - this.initializeNodeTransformers(node, parentNode, Obfuscator.nodeObfuscators); - } - - /** - * @param node - * @param parentNode - * @param nodeTransformersMap - */ - private initializeNodeTransformers ( - node: ESTree.Node, - parentNode: ESTree.Node, - nodeTransformersMap: Map + private transformAstTree ( + astTree: ESTree.Program, + direction: TVisitorDirection, + nodeTransformersFactory: INodeTransformersFactory ): void { - let nodeTransformers: TNodeTransformer[] | undefined = nodeTransformersMap.get(node.type); + estraverse.traverse(astTree, { + [direction]: (node: ESTree.Node, parentNode: ESTree.Node): void => { + const nodeTransformers: INodeTransformer[] = nodeTransformersFactory.initializeNodeTransformers(node.type); - if (!nodeTransformers) { - return; - } - - nodeTransformers.forEach((transformer: TNodeTransformer) => { - new transformer(this.customNodes, this.options).transformNode(node, parentNode); - }); - } - - /** - * @param node - */ - private obfuscate (node: ESTree.Node): void { - // first pass: control flow flattening - if (this.options.controlFlowFlattening) { - estraverse.traverse(node, { - leave: (node: ESTree.Node, parentNode: ESTree.Node): void => { - this.initializeNodeControlFlowChangers(node, parentNode); - } - }); - } - - // second pass: nodes obfuscation - estraverse.traverse(node, { - enter: (node: ESTree.Node, parentNode: ESTree.Node): void => { - this.initializeNodeObfuscators(node, parentNode); + nodeTransformers.forEach((nodeTransformer: INodeTransformer) => { + nodeTransformer.transformNode(node, parentNode); + }); } }); } diff --git a/src/SourceMapCorrector.ts b/src/SourceMapCorrector.ts index 52c937b7..8c60cd4c 100644 --- a/src/SourceMapCorrector.ts +++ b/src/SourceMapCorrector.ts @@ -12,22 +12,22 @@ export class SourceMapCorrector implements ISourceMapCorrector { /** * @type {string} */ - private obfuscatedCode: string; + private readonly obfuscatedCode: string; /** * @type {string} */ - private sourceMap: string; + private readonly sourceMap: string; /** * @type {TSourceMapMode} */ - private sourceMapMode: TSourceMapMode; + private readonly sourceMapMode: TSourceMapMode; /** * @type {string} */ - private sourceMapUrl: string; + private readonly sourceMapUrl: string; /** * @param obfuscationResult diff --git a/src/enums/VisitorDirection.ts b/src/enums/VisitorDirection.ts new file mode 100644 index 00000000..b21f6532 --- /dev/null +++ b/src/enums/VisitorDirection.ts @@ -0,0 +1,6 @@ +import { Utils } from '../Utils'; + +export const VisitorDirection: any = Utils.strEnumify({ + enter: 'enter', + leave: 'leave' +}); diff --git a/src/interfaces/INodeTransformersFactory.d.ts b/src/interfaces/INodeTransformersFactory.d.ts new file mode 100644 index 00000000..124e21e2 --- /dev/null +++ b/src/interfaces/INodeTransformersFactory.d.ts @@ -0,0 +1,5 @@ +import { INodeTransformer } from './INodeTransformer'; + +export interface INodeTransformersFactory { + initializeNodeTransformers (nodeType: string): INodeTransformer[]; +} diff --git a/src/interfaces/IObfuscator.d.ts b/src/interfaces/IObfuscator.d.ts index 25f1fbbb..51bac08d 100644 --- a/src/interfaces/IObfuscator.d.ts +++ b/src/interfaces/IObfuscator.d.ts @@ -1,5 +1,5 @@ import * as ESTree from 'estree'; export interface IObfuscator { - obfuscateNode (node: ESTree.Node): ESTree.Node; + obfuscateAstTree (node: ESTree.Program): ESTree.Program; } diff --git a/src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer.d.ts b/src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer.d.ts index 293657f6..e3609720 100644 --- a/src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer.d.ts +++ b/src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer.d.ts @@ -1,5 +1,7 @@ +import * as ESTree from 'estree'; + import { IStackTraceData } from './IStackTraceData'; export interface IStackTraceAnalyzer { - analyze (): IStackTraceData[]; + analyze (blockScopeBody: ESTree.Node[]): IStackTraceData[]; } diff --git a/src/node-transformers/NodeControlFlowTransformersFactory.ts b/src/node-transformers/NodeControlFlowTransformersFactory.ts new file mode 100644 index 00000000..2d10e1d5 --- /dev/null +++ b/src/node-transformers/NodeControlFlowTransformersFactory.ts @@ -0,0 +1,57 @@ +import { TNodeTransformer } from '../types/TNodeTransformer'; + +import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode'; +import { INodeTransformer } from '../interfaces/INodeTransformer'; +import { INodeTransformersFactory } from '../interfaces/INodeTransformersFactory'; +import { IOptions } from '../interfaces/IOptions'; + +import { NodeType } from '../enums/NodeType'; + +import { FunctionControlFlowTransformer } from './node-control-flow-transformers/FunctionControlFlowTransformer'; + + +export class NodeControlFlowTransformersFactory implements INodeTransformersFactory { + /** + * @type {Map} + */ + private static readonly nodeControlFlowChangers: Map = new Map ([ + [NodeType.FunctionDeclaration, [FunctionControlFlowTransformer]], + [NodeType.FunctionExpression, [FunctionControlFlowTransformer]] + ]); + + /** + * @type Map + */ + protected customNodes: Map ; + + /** + * @type {IOptions} + */ + protected options: IOptions; + + /** + * @param customNodes + * @param options + */ + constructor(customNodes: Map , options: IOptions) { + this.customNodes = customNodes; + this.options = options; + } + + /** + * @param nodeType + * @returns {INodeTransformer[]} + */ + public initializeNodeTransformers (nodeType: string): INodeTransformer[] { + const nodeObfuscators: TNodeTransformer[] = NodeControlFlowTransformersFactory.nodeControlFlowChangers.get(nodeType) || []; + const instancesArray: INodeTransformer[] = []; + + nodeObfuscators.forEach((transformer: TNodeTransformer) => { + instancesArray.push( + new transformer(this.customNodes, this.options) + ); + }); + + return instancesArray; + } +} diff --git a/src/node-transformers/NodeObfuscatorsFactory.ts b/src/node-transformers/NodeObfuscatorsFactory.ts new file mode 100644 index 00000000..c7332924 --- /dev/null +++ b/src/node-transformers/NodeObfuscatorsFactory.ts @@ -0,0 +1,76 @@ +import { TNodeTransformer } from '../types/TNodeTransformer'; + +import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode'; +import { INodeTransformer } from '../interfaces/INodeTransformer'; +import { INodeTransformersFactory } from '../interfaces/INodeTransformersFactory'; +import { IOptions } from '../interfaces/IOptions'; + +import { NodeType } from '../enums/NodeType'; + +import { CatchClauseObfuscator } from './node-obfuscators/CatchClauseObfuscator'; +import { FunctionDeclarationObfuscator } from './node-obfuscators/FunctionDeclarationObfuscator'; +import { FunctionObfuscator } from './node-obfuscators/FunctionObfuscator'; +import { LabeledStatementObfuscator } from './node-obfuscators/LabeledStatementObfuscator'; +import { LiteralObfuscator } from './node-obfuscators/LiteralObfuscator'; +import { MemberExpressionObfuscator } from './node-obfuscators/MemberExpressionObfuscator'; +import { MethodDefinitionObfuscator } from './node-obfuscators/MethodDefinitionObfuscator'; +import { ObjectExpressionObfuscator } from './node-obfuscators/ObjectExpressionObfuscator'; +import { VariableDeclarationObfuscator } from './node-obfuscators/VariableDeclarationObfuscator'; + +export class NodeObfuscatorsFactory implements INodeTransformersFactory { + /** + * @type {Map} + */ + private static readonly nodeObfuscators: Map = new Map ([ + [NodeType.ArrowFunctionExpression, [FunctionObfuscator]], + [NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]], + [NodeType.CatchClause, [CatchClauseObfuscator]], + [NodeType.FunctionDeclaration, [ + FunctionDeclarationObfuscator, + FunctionObfuscator + ]], + [NodeType.FunctionExpression, [FunctionObfuscator]], + [NodeType.MemberExpression, [MemberExpressionObfuscator]], + [NodeType.MethodDefinition, [MethodDefinitionObfuscator]], + [NodeType.ObjectExpression, [ObjectExpressionObfuscator]], + [NodeType.VariableDeclaration, [VariableDeclarationObfuscator]], + [NodeType.LabeledStatement, [LabeledStatementObfuscator]], + [NodeType.Literal, [LiteralObfuscator]] + ]); + + /** + * @type Map + */ + protected customNodes: Map ; + + /** + * @type {IOptions} + */ + protected options: IOptions; + + /** + * @param customNodes + * @param options + */ + constructor(customNodes: Map , options: IOptions) { + this.customNodes = customNodes; + this.options = options; + } + + /** + * @param nodeType + * @returns {INodeTransformer[]} + */ + public initializeNodeTransformers (nodeType: string): INodeTransformer[] { + const nodeObfuscators: TNodeTransformer[] = NodeObfuscatorsFactory.nodeObfuscators.get(nodeType) || []; + const instancesArray: INodeTransformer[] = []; + + nodeObfuscators.forEach((transformer: TNodeTransformer) => { + instancesArray.push( + new transformer(this.customNodes, this.options) + ); + }); + + return instancesArray; + } +} diff --git a/src/stack-trace-analyzer/StackTraceAnalyzer.ts b/src/stack-trace-analyzer/StackTraceAnalyzer.ts index c30155b1..a6346d92 100644 --- a/src/stack-trace-analyzer/StackTraceAnalyzer.ts +++ b/src/stack-trace-analyzer/StackTraceAnalyzer.ts @@ -58,11 +58,6 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer { */ private static limitThreshold: number = 0.002; - /** - * @type {ESTree.Node[]} - */ - private blockScopeBody: ESTree.Node[]; - /** * @type {Map} */ @@ -72,13 +67,6 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer { [NodeType.ObjectExpression, ObjectExpressionCalleeDataExtractor] ]); - /** - * @param blockScopeBody - */ - constructor (blockScopeBody: ESTree.Node[]) { - this.blockScopeBody = blockScopeBody; - } - /** * @param blockScopeBodyLength * @returns {number} @@ -103,10 +91,11 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer { } /** + * @param blockScopeBody * @returns {IStackTraceData[]} */ - public analyze (): IStackTraceData[] { - return this.analyzeRecursive(this.blockScopeBody); + public analyze (blockScopeBody: ESTree.Node[]): IStackTraceData[] { + return this.analyzeRecursive(blockScopeBody); } /** diff --git a/src/types/TVisitorDirection.d.ts b/src/types/TVisitorDirection.d.ts new file mode 100644 index 00000000..830fc4be --- /dev/null +++ b/src/types/TVisitorDirection.d.ts @@ -0,0 +1 @@ +export type TVisitorDirection = 'enter' | 'leave'; diff --git a/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts b/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts index 7e59d3f3..a7bd66e4 100644 --- a/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts +++ b/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts @@ -4,6 +4,8 @@ import { JavaScriptObfuscatorInternal } from '../../src/JavaScriptObfuscatorInte import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset'; +import { Options } from '../../src/options/Options'; + const assert: Chai.AssertStatic = require('chai').assert; describe('JavaScriptObfuscatorInternal', () => { @@ -14,16 +16,15 @@ describe('JavaScriptObfuscatorInternal', () => { it('should link obfuscated code with source map', () => { javaScriptObfuscator = new JavaScriptObfuscatorInternal( - `var test = 1;`, - Object.assign({}, NO_CUSTOM_NODES_PRESET, { - sourceMap: true, - sourceMapFileName: sourceMapUrl - }) + new Options( + Object.assign({}, NO_CUSTOM_NODES_PRESET, { + sourceMap: true, + sourceMapFileName: sourceMapUrl + }) + ) ); - javaScriptObfuscator.obfuscate(); - - obfuscationResult = javaScriptObfuscator.getObfuscationResult(); + obfuscationResult = javaScriptObfuscator.obfuscate('var test = 1;'); assert.match( obfuscationResult.getObfuscatedCode(), @@ -36,17 +37,16 @@ describe('JavaScriptObfuscatorInternal', () => { let sourceMapBaseUrl: string = 'http://localhost:9000'; javaScriptObfuscator = new JavaScriptObfuscatorInternal( - `var test = 1;`, - Object.assign({}, NO_CUSTOM_NODES_PRESET, { - sourceMap: true, - sourceMapBaseUrl: sourceMapBaseUrl, - sourceMapFileName: sourceMapUrl - }) + new Options( + Object.assign({}, NO_CUSTOM_NODES_PRESET, { + sourceMap: true, + sourceMapBaseUrl: sourceMapBaseUrl, + sourceMapFileName: sourceMapUrl + }) + ) ); - javaScriptObfuscator.obfuscate(); - - obfuscationResult = javaScriptObfuscator.getObfuscationResult(); + obfuscationResult = javaScriptObfuscator.obfuscate('var test = 1;'); assert.match( obfuscationResult.getObfuscatedCode(), diff --git a/test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts b/test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts index 9f57f12e..86859603 100644 --- a/test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts +++ b/test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec.ts @@ -4,6 +4,7 @@ import * as ESTree from 'estree'; import { TNodeWithBlockStatement } from '../../../src/types/TNodeWithBlockStatement'; +import { IStackTraceAnalyzer } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer'; import { IStackTraceData } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceData'; import { readFileAsString } from '../../helpers/readFileAsString'; @@ -145,6 +146,8 @@ function getObjectFunctionExpressionByName (astTree: ESTree.Node, objectName: st describe('StackTraceAnalyzer', () => { describe('extract (): IStackTraceData[]', () => { + const stackTraceAnalyzer: IStackTraceAnalyzer = new StackTraceAnalyzer(); + let astTree: TNodeWithBlockStatement, stackTraceData: IStackTraceData[], expectedStackTraceData: IStackTraceData[]; @@ -191,7 +194,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -227,7 +230,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -263,7 +266,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -283,7 +286,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -339,7 +342,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -364,7 +367,7 @@ describe('StackTraceAnalyzer', () => { }, ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -378,7 +381,7 @@ describe('StackTraceAnalyzer', () => { expectedStackTraceData = []; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -392,7 +395,7 @@ describe('StackTraceAnalyzer', () => { expectedStackTraceData = []; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -424,7 +427,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); @@ -444,7 +447,7 @@ describe('StackTraceAnalyzer', () => { } ]; - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); assert.deepEqual(stackTraceData, expectedStackTraceData); }); diff --git a/test/unit-tests/node/NodeAppender.spec.ts b/test/unit-tests/node/NodeAppender.spec.ts index e88c63d6..7db6461b 100644 --- a/test/unit-tests/node/NodeAppender.spec.ts +++ b/test/unit-tests/node/NodeAppender.spec.ts @@ -3,6 +3,7 @@ import * as ESTree from 'estree'; import { TStatement } from '../../../src/types/TStatement'; +import { IStackTraceAnalyzer } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer'; import { IStackTraceData } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceData'; import { readFileAsString } from '../../helpers/readFileAsString'; @@ -49,6 +50,8 @@ describe('NodeAppender', () => { }); describe('appendNodeToOptimalBlockScope (blockScopeStackTraceData: IStackTraceData[], blockScopeNode: TNodeWithBlockStatement, nodeBodyStatements: TStatement[], index: number = 0): void', () => { + const stackTraceAnalyzer: IStackTraceAnalyzer = new StackTraceAnalyzer(); + let astTree: ESTree.Program, expectedAstTree: ESTree.Program, node: TStatement[], @@ -73,7 +76,7 @@ describe('NodeAppender', () => { ) ); - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node); assert.deepEqual(astTree, expectedAstTree); @@ -92,7 +95,7 @@ describe('NodeAppender', () => { ) ); - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node); assert.deepEqual(astTree, expectedAstTree); @@ -118,7 +121,7 @@ describe('NodeAppender', () => { ) ); - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node, 2); assert.deepEqual(astTree, expectedAstTree); @@ -132,7 +135,7 @@ describe('NodeAppender', () => { ) ); - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node, 1); assert.deepEqual(astTree, expectedAstTree); @@ -150,7 +153,7 @@ describe('NodeAppender', () => { ) ); - stackTraceData = new StackTraceAnalyzer(astTree.body).analyze(); + stackTraceData = stackTraceAnalyzer.analyze(astTree.body); NodeAppender.appendNodeToOptimalBlockScope( stackTraceData, astTree,