Merge branch 'dev'

# Conflicts:
#	CHANGELOG.md
#	dist/index.js
#	package.json
#	src/Nodes.ts
#	src/Obfuscator.ts
#	src/interfaces/nodes/INode.d.ts
#	src/node-obfuscators/CatchClauseObfuscator.ts
#	src/node-obfuscators/FunctionDeclarationObfuscator.ts
#	src/node-obfuscators/FunctionObfuscator.ts
#	src/node-obfuscators/MemberExpressionObfuscator.ts
#	src/node-obfuscators/ObjectExpressionObfuscator.ts
#	src/node-obfuscators/VariableDeclarationObfuscator.ts
#	test/functional-tests/node-obfuscators/FunctionObfuscator.spec.ts
#	test/functional-tests/node-obfuscators/VariableDeclarationObfuscator.spec.ts
#	test/index.spec.ts
#	test/mocks/NodeMocks.ts
#	test/unit-tests/NodeUtils.spec.ts
This commit is contained in:
sanex3339
2016-11-06 21:32:40 +03:00
202 changed files with 83771 additions and 2703 deletions
+19
View File
@@ -0,0 +1,19 @@
'use strict';
import * as fs from 'fs';
if (!(<any>global)._babelPolyfill) {
require('babel-polyfill');
}
(function () {
const JavaScriptObfuscator: any = require("../../index");
let start: any = new Date();
JavaScriptObfuscator.obfuscate(
fs.readFileSync('test/fixtures/compile-performance.js', 'utf8')
).getObfuscatedCode();
console.log(`Total time: ${<any>new Date() - start}`);
})();
+84
View File
@@ -0,0 +1,84 @@
'use strict';
if (!(<any>global)._babelPolyfill) {
require('babel-polyfill');
}
(function () {
const JavaScriptObfuscator: any = require("../../index");
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var start = new Date();
var log = console.log;
console.log = function () {};
${String(`
var result = 1,
term1 = 0,
term2 = 1,
i = 1;
while(i < 10)
{
var test = 10;
result = term1 + term2;
console.log(result);
term1 = term2;
term2 = result;
i++;
}
console.log(test);
var test = function (test) {
console.log(test);
if (true) {
var test = 5
}
return test;
}
console.log(test(1));
function test2 (abc) {
function test1 () {
console.log('inside', abc.item);
}
console.log('тест', abc);
var abc = {};
return abc.item = 15, test1();
};
var regexptest = /version\\/(\\d+)/i;
console.log(regexptest);
test2(22);
console.log(105.4);
console.log(true, false);
var sA = 'shorthand1';
var sB = 'shorthand2';
console.log({sA, sB});
try {
} catch (error) {
console.log(error);
}
`).repeat(1000)}
console.log = log;
console.log(new Date() - start);
`,
{
disableConsoleOutput: false,
}
).getObfuscatedCode();
console.log(eval(obfuscatedCode));
})();
+13 -10
View File
@@ -4,10 +4,11 @@ if (!(<any>global)._babelPolyfill) {
require('babel-polyfill');
}
const JavaScriptObfuscator: any = require("../../index");
(function () {
const JavaScriptObfuscator: any = require("../../index");
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
(function(){
var result = 1,
term1 = 0,
@@ -67,11 +68,13 @@ let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
}
})();
`,
{
disableConsoleOutput: false,
encodeUnicodeLiterals: true
}
).getObfuscatedCode();
{
disableConsoleOutput: false,
unicodeArrayEncoding: 'rc4',
selfDefending: true
}
).getObfuscatedCode();
console.log(obfuscatedCode);
console.log(eval(obfuscatedCode));
console.log(obfuscatedCode);
console.log(eval(obfuscatedCode));
})();
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
var func = function () {
return true;
};
var test = 1;
@@ -0,0 +1,28 @@
function foo () {
var test = 1;
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
}
bar();
baz();
foo();
@@ -0,0 +1,28 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
var test = 1;
}
bar();
baz();
foo();
@@ -0,0 +1,27 @@
var start = new Date();
var log = console.log;
console.log = function () {};
(function () {
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
var test = 1;
}
inner3();
}
inner2();
inner1();
}
bar();
})();
console.log = log;
console.log(new Date() - start);
@@ -0,0 +1,27 @@
var start = new Date();
var log = console.log;
console.log = function () {};
(function () {
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
}
inner3();
}
inner2();
inner1();
}
bar();
})();
console.log = log;
console.log(new Date() - start);
@@ -0,0 +1,28 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
}
bar();
baz();
foo();
@@ -0,0 +1,27 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
var test = 1;
}
baz();
foo();
bar();
@@ -0,0 +1,28 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
}
baz();
foo();
bar();
@@ -0,0 +1,28 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
var test = 1;
};
inner3();
}
inner2();
inner1();
}
function baz () {
}
bar();
baz();
foo();
@@ -0,0 +1,28 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
}
bar();
baz();
foo();
+3
View File
@@ -0,0 +1,3 @@
var func = function () {
return true;
};
@@ -0,0 +1,13 @@
var func1 = function () {
return true;
};
var func2 = function () {
return false;
};
var test = 1;
var func3 = function () {
return 'string';
};
+11
View File
@@ -0,0 +1,11 @@
var func1 = function () {
return true;
};
var func2 = function () {
return false;
};
var func3 = function () {
return 'string';
};
+5
View File
@@ -0,0 +1,5 @@
var test = 1;
var func = function () {
return true;
};
+3
View File
@@ -0,0 +1,3 @@
var func = function () {
return true;
};
+6 -1
View File
@@ -46,8 +46,13 @@
console.log(105.4);
console.log(true, false);
var sA = 'shorthand1';
var sB = 'shorthand2';
console.log({sA, sB});
try {
} catch (error) {
console.log(error);
}
})();
})();
+28
View File
@@ -0,0 +1,28 @@
function foo () {
}
function bar () {
function inner1 () {
}
function inner2 () {
var inner3 = function () {
};
inner3();
}
inner2();
inner1();
}
function baz () {
}
baz();
foo();
bar();
+20
View File
@@ -0,0 +1,20 @@
bar();
function foo () {
}
function bar () {
}
function baz () {
function inner1 () {
}
inner1();
}
baz();
foo();
@@ -0,0 +1,5 @@
bar();
function bar () {
}
@@ -0,0 +1,42 @@
var object = {
foo: {
baz: function () {
}
},
bar: function () {
function inner () {
}
inner();
}
};
var object1 = {
foo: {
baz: function () {
},
func: function () {
}
},
'bar': function () {
function inner1 () {
}
inner1();
}
};
object1.foo.baz();
object1['foo'].baz();
object1['foo'].func();
object1.bar();
object.bar();
@@ -0,0 +1,27 @@
bar();
function foo () {
}
function bar () {
}
function baz () {
function inner1 () {
}
if (true) {
switch (true) {
case true:
while (true) {
inner1();
}
}
}
}
baz();
foo();
@@ -0,0 +1,7 @@
function bar () {
}
function baz () {
}
+4
View File
@@ -0,0 +1,4 @@
var bar = function () {
};
bar();
@@ -0,0 +1 @@
bar();
@@ -0,0 +1,11 @@
(function foo (){
(function bar (){
!function baz (){
inner();
function inner () {
}
}();
}());
})();
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
import { JavaScriptObfuscator } from "../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
import { NO_CUSTOM_NODES_PRESET } from "../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -33,7 +33,7 @@ describe('JavaScriptObfuscator', () => {
assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings);
});
it('should returns object with obfuscated code with inline source map and empty `sourceMap` if `sourceMapMode` is `inline', () => {
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, {
@@ -47,7 +47,7 @@ describe('JavaScriptObfuscator', () => {
obfuscationResult.getObfuscatedCode(),
/sourceMappingURL=data:application\/json;base64/
);
assert.isNotOk(obfuscationResult.getSourceMap());
assert.isOk(obfuscationResult.getSourceMap());
});
it('should returns object with empty obfuscated code and source map with empty data if source code is empty', () => {
@@ -102,29 +102,28 @@ describe('JavaScriptObfuscator', () => {
});
it('should obfuscate simple code with literal variable value', () => {
let pattern: RegExp = /^var _0x(\w){4} *= *\['(\\[x|u]\d+)+'\]; *var *test *= *_0x(\w){4}\[0x0\];$/;
assert.match(
JavaScriptObfuscator.obfuscate(
let pattern1: RegExp = /^var _0x(\w){4} *= *\['(\\[x|u]\d+)+'\];/,
pattern2: RegExp = /var *test *= *_0x(\w){4}\('0x0'\);$/,
obfuscatedCode1: string = JavaScriptObfuscator.obfuscate(
`var test = 'abc';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
unicodeArray: true,
unicodeArrayThreshold: 1
})
).getObfuscatedCode(),
pattern
);
assert.match(
JavaScriptObfuscator.obfuscate(
obfuscatedCode2: string = JavaScriptObfuscator.obfuscate(
`var test = 'абц';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
unicodeArray: true,
unicodeArrayThreshold: 1
})
).getObfuscatedCode(),
pattern
);
).getObfuscatedCode();
assert.match(obfuscatedCode1, pattern1);
assert.match(obfuscatedCode1, pattern2);
assert.match(obfuscatedCode2, pattern1);
assert.match(obfuscatedCode2, pattern2);
});
});
});
@@ -2,9 +2,9 @@ import * as fs from 'fs';
import * as mkdirp from 'mkdirp';
import * as sinon from 'sinon';
import { StdoutWriteMock } from "../mocks/StdoutWriteMock";
import { StdoutWriteMock } from '../mocks/StdoutWriteMock';
import { JavaScriptObfuscator } from "../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -87,34 +87,125 @@ describe('JavaScriptObfuscatorCLI', function (): void {
describe('--sourceMap option is set', () => {
let outputSourceMapPath: string = `${outputFilePath}.map`;
it('should creates file with source map in the same directory as output file', () => {
JavaScriptObfuscator.runCLI([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--selfDefending',
'0',
'--sourceMap',
'true'
]);
describe('--sourceMapMode option is `separate`', () => {
it('should creates file with source map in the same directory as output file', () => {
JavaScriptObfuscator.runCLI([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--selfDefending',
'0',
'--sourceMap',
'true'
]);
assert.equal(fs.existsSync(outputSourceMapPath), true);
assert.equal(fs.existsSync(outputSourceMapPath), true);
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }),
sourceMap: any = JSON.parse(content);
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }),
sourceMap: any = JSON.parse(content);
assert.property(sourceMap, 'version');
assert.property(sourceMap, 'sources');
assert.property(sourceMap, 'names');
assert.property(sourceMap, 'version');
assert.property(sourceMap, 'sources');
assert.property(sourceMap, 'names');
});
it('should creates file with source map in the same directory as output file if `sourceMapBaseUrl` is set', () => {
JavaScriptObfuscator.runCLI([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--selfDefending',
'0',
'--sourceMap',
'true',
'--sourceMapBaseUrl',
'http://localhost:9000/'
]);
assert.equal(fs.existsSync(outputSourceMapPath), true);
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }),
sourceMap: any = JSON.parse(content);
assert.property(sourceMap, 'version');
assert.property(sourceMap, 'sources');
assert.property(sourceMap, 'names');
});
afterEach(() => {
fs.unlinkSync(outputSourceMapPath);
});
});
describe('--sourceMapFileName option is set', () => {
let sourceMapFileName: string = 'test',
sourceMapFilePath: string = `${sourceMapFileName}.js.map`,
outputSourceMapFilePath: string = `${outputDirName}/${sourceMapFilePath}`;
it('should creates source map file with given name in the same directory as output file', () => {
JavaScriptObfuscator.runCLI([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--selfDefending',
'0',
'--sourceMap',
'true',
'--sourceMapFileName',
sourceMapFileName
]);
assert.equal(fs.existsSync(outputSourceMapFilePath), true);
const content: string = fs.readFileSync(outputSourceMapFilePath, { encoding: 'utf8' }),
sourceMap: any = JSON.parse(content);
assert.property(sourceMap, 'version');
assert.property(sourceMap, 'sources');
assert.property(sourceMap, 'names');
});
afterEach(() => {
fs.unlinkSync(outputSourceMapFilePath);
});
});
describe('--sourceMapMode option is `inline`', () => {
it('shouldn\'t create file with source map if `sourceMapMode` is `inline`', () => {
JavaScriptObfuscator.runCLI([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--selfDefending',
'0',
'--sourceMap',
'true',
'--sourceMapMode',
'inline'
]);
assert.equal(fs.existsSync(outputSourceMapPath), false);
});
});
afterEach(() => {
fs.unlinkSync(outputFilePath);
fs.unlinkSync(outputSourceMapPath);
});
});
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
import { JavaScriptObfuscatorInternal } from "../../src/JavaScriptObfuscatorInternal";
import { JavaScriptObfuscatorInternal } from '../../src/JavaScriptObfuscatorInternal';
import { NO_CUSTOM_NODES_PRESET } from "../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../src/preset-options/NoCustomNodesPreset';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -10,28 +10,49 @@ describe('JavaScriptObfuscatorInternal', () => {
describe(`setSourceMapUrl (url: string)`, () => {
let javaScriptObfuscator: JavaScriptObfuscatorInternal,
obfuscationResult: IObfuscationResult,
sourceMapUrl: string = 'test.map.js';
sourceMapUrl: string = 'test.js.map';
beforeEach(() => {
it('should link obfuscated code with source map', () => {
javaScriptObfuscator = new JavaScriptObfuscatorInternal(
`var test = 1;`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
sourceMap: true
sourceMap: true,
sourceMapFileName: sourceMapUrl
})
);
javaScriptObfuscator.obfuscate();
javaScriptObfuscator.setSourceMapUrl(sourceMapUrl);
obfuscationResult = javaScriptObfuscator.getObfuscationResult();
});
it('should link obfuscated code with source map', () => {
assert.match(
obfuscationResult.getObfuscatedCode(),
new RegExp(`sourceMappingURL=${sourceMapUrl}`))
;
assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings);
});
it('should properly add base url to source map import inside obfuscated code if `sourceMapBaseUrl` is set', () => {
let sourceMapBaseUrl: string = 'http://localhost:9000';
javaScriptObfuscator = new JavaScriptObfuscatorInternal(
`var test = 1;`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
sourceMap: true,
sourceMapBaseUrl: sourceMapBaseUrl,
sourceMapFileName: sourceMapUrl
})
);
javaScriptObfuscator.obfuscate();
obfuscationResult = javaScriptObfuscator.getObfuscationResult();
assert.match(
obfuscationResult.getObfuscatedCode(),
new RegExp(`sourceMappingURL=${sourceMapBaseUrl}/${sourceMapUrl}$`))
;
assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings);
});
});
});
@@ -0,0 +1,34 @@
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 appendNodeToOptimalBlockScope `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, {
disableConsoleOutput: true
})
);
assert.match(obfuscationResult.getObfuscatedCode(), regExp);
});
it('should\'t appendNodeToOptimalBlockScope `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, {
disableConsoleOutput: false,
unicodeArrayThreshold: 1
})
);
assert.notMatch(obfuscationResult.getObfuscatedCode(), regExp);
});
});
@@ -0,0 +1,31 @@
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 appendNodeToOptimalBlockScope `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, {
domainLock: ['.example.com']
})
);
assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
});
it('should\'t appendNodeToOptimalBlockScope `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, {
domainLock: []
})
);
assert.notMatch(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *new RegExp/);
});
});
@@ -0,0 +1,25 @@
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('UnicodeArrayCallsWrapper', () => {
it('should correctly appendNodeToOptimalBlockScope `UnicodeArrayCallsWrapper` custom node into the obfuscated code', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
unicodeArray: true,
unicodeArrayThreshold: 1,
wrapUnicodeArrayCalls: true
})
);
assert.match(
obfuscationResult.getObfuscatedCode(),
/var *_0x([a-z0-9]){4,6} *= *parseInt\(_0x([a-z0-9]){4,6}, *0x10\);/
);
});
});
@@ -0,0 +1,32 @@
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('UnicodeArrayNode', () => {
it('should correctly appendNodeToOptimalBlockScope `UnicodeArrayNode` custom node into the obfuscated code if `unicodeArray` option is set', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
unicodeArray: true,
unicodeArrayThreshold: 1
})
);
assert.match(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
});
it('should\'t appendNodeToOptimalBlockScope `UnicodeArrayNode` custom node into the obfuscated code if `unicodeArray` option is not set', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
unicodeArray: false
})
);
assert.notMatch(obfuscationResult.getObfuscatedCode(), /^var _0x([a-z0-9]){4} *= *\[/);
});
});
@@ -0,0 +1,35 @@
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('UnicodeArrayRotateFunctionNode', () => {
it('should correctly appendNodeToOptimalBlockScope `UnicodeArrayRotateFunctionNode` custom node into the obfuscated code if `rotateUnicodeArray` option is set', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
rotateUnicodeArray: true,
unicodeArray: true,
unicodeArrayThreshold: 1
})
);
assert.match(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
});
it('should\'t appendNodeToOptimalBlockScope `UnicodeArrayRotateFunctionNode` custom node into the obfuscated code if `rotateUnicodeArray` option is not set', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
rotateUnicodeArray: false,
unicodeArray: true,
unicodeArrayThreshold: 1
})
);
assert.notMatch(obfuscationResult.getObfuscatedCode(), /while *\(-- *_0x([a-z0-9]){4,6}\) *\{/);
});
});
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -29,9 +29,9 @@ describe('FunctionObfuscator', () => {
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/var _0x[a-z0-9]{5,6} *= *function *\((_0x[a-z0-9]{5,6})\) *\{/);
.match(/var _0x[a-z0-9]{4,6} *= *function *\((_0x[a-z0-9]{4,6})\) *\{/);
const functionBodyIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{5,6})\)/);
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{4,6})\)/);
const functionParamIdentifierName: string = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
const functionBodyIdentifierName: string = (<RegExpMatchArray>functionBodyIdentifierMatch)[1];
@@ -1,14 +1,14 @@
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
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 value without encoding to base64', () => {
it('should replace literal node value with unicode value without encoding', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
@@ -17,26 +17,72 @@ describe('LiteralObfuscator', () => {
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *'\\x74\\x65\\x73\\x74';$/);
});
it('should replace literal node value with unicode value with encoding to base64', () => {
it('should replace literal node value with unicode array value', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 'test';`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
encodeUnicodeLiterals: true,
unicodeArray: true,
unicodeArrayThreshold: 1
})
);
assert.match(obfuscationResult.getObfuscatedCode(), /^var *_0x([a-z0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/);
assert.match(
obfuscationResult.getObfuscatedCode(),
/^var *_0x([a-z0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
});
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, {
unicodeArray: true,
unicodeArrayThreshold: 1
})
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *'\\x74\\x65';/);
});
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, {
unicodeArray: true,
unicodeArrayEncoding: 'base64',
unicodeArrayThreshold: 1
})
);
assert.match(
obfuscationResult.getObfuscatedCode(),
/^var *_0x([a-z0-9]){4} *= *\['\\x64\\x47\\x56\\x7a\\x64\\x41\\x3d\\x3d'\];/
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
});
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, {
unicodeArray: true,
unicodeArrayEncoding: 'rc4',
unicodeArrayThreshold: 1
})
);
assert.match(
obfuscationResult.getObfuscatedCode(),
/var *test *= *_0x([a-z0-9]){4}\('0x0', '(\\x[a-f0-9]*){4}'\);/
);
});
});
it('should obfuscate literal node with boolean value', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = true;`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
encodeUnicodeLiterals: true,
unicodeArray: true,
unicodeArrayThreshold: 1
})
@@ -49,7 +95,6 @@ describe('LiteralObfuscator', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`var test = 0;`,
Object.assign({}, NO_CUSTOM_NODES_PRESET, {
encodeUnicodeLiterals: true,
unicodeArray: true,
unicodeArrayThreshold: 1
})
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -27,7 +27,7 @@ describe('MemberExpressionObfuscator', () => {
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\[0x0\]\];/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\('0x0'\)\];/);
});
});
@@ -42,7 +42,7 @@ describe('MemberExpressionObfuscator', () => {
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4} *= *\['\\x6c\\x6f\\x67'\];/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\[0x0\]\];/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *console\[_0x([a-z0-9]){4}\('0x0'\)\];/);
});
it('should ignore square brackets call with identifier value', () => {
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -33,7 +33,7 @@ describe('MethodDefinitionObfuscator', () => {
);
assert.match(obfuscationResult.getObfuscatedCode(), /var *_0x([a-z0-9]){4} *= *\['\\x62\\x61\\x72'\];/);
assert.match(obfuscationResult.getObfuscatedCode(), /\[_0x([a-z0-9]){4}\[0x0\]\]\(\)\{\}/);
assert.match(obfuscationResult.getObfuscatedCode(), /\[_0x([a-z0-9]){4}\('0x0'\)\]\(\)\{\}/);
});
it('should not obfuscate method definition node with `constructor` key', () => {
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -13,7 +13,7 @@ describe('ObjectExpressionObfuscator', () => {
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *\{'\\x66\\x6f\\x6f':0x0\};$/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
});
it('should replace object expression node `key` property with identifier value by unicode value', () => {
@@ -22,7 +22,25 @@ describe('ObjectExpressionObfuscator', () => {
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *\{'\\x66\\x6f\\x6f':0x0\};$/);
assert.match(obfuscationResult.getObfuscatedCode(), /var *test *= *\{'\\x66\\x6f\\x6f':0x0\};/);
});
it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`
(function () {
let a = 0;
let b = 0;
var test = {a, b};
})();
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
assert.match(
obfuscationResult.getObfuscatedCode(),
/var *_0x[a-z0-9]{4,6} *= *\{'\\x61': *_0x[a-z0-9]{4,6}\, *'\\x62': *_0x[a-z0-9]{4,6}\};/
);
});
it('should correct convert shorthand ES6 object expression to non-shorthand object expression', () => {
@@ -1,8 +1,8 @@
import { IObfuscationResult } from "../../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../../src/interfaces/IObfuscationResult';
import { NO_CUSTOM_NODES_PRESET } from "../../../src/preset-options/NoCustomNodesPreset";
import { NO_CUSTOM_NODES_PRESET } from '../../../src/preset-options/NoCustomNodesPreset';
import { JavaScriptObfuscator } from "../../../src/JavaScriptObfuscator";
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -38,64 +38,6 @@ describe('VariableDeclarationObfuscator', () => {
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
});
describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
let obfuscationResult: IObfuscationResult,
functionParamIdentifierName: string|null,
innerFunctionParamIdentifierName: string|null,
constructorIdentifierName: string|null,
objectIdentifierName: string|null,
variableDeclarationIdentifierName: string|null;
beforeEach(() => {
obfuscationResult = JavaScriptObfuscator.obfuscate(
`
(function () {
function foo (t, e) {
return function () {
function baz (t) {
console.log(t);
}
return {t: t};
var t;
}();
}
})();
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
});
it('should correct obfuscate variables inside function body', () => {
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/function *_0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\,(_0x[a-z0-9]{5,6})\) *\{/);
const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/function _0x[a-z0-9]{5,6} *\((_0x[a-z0-9]{5,6})\) *\{/);
const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{5,6})\)/);
const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/return\{'\\x74':(_0x[a-z0-9]{5,6})\}/);
const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/var *(_0x[a-z0-9]{5,6});/);
functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
assert.equal(functionParamIdentifierName, objectIdentifierName);
assert.equal(functionParamIdentifierName, variableDeclarationIdentifierName);
assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
});
});
it('should not obfuscate variable call (`identifier` node) outside of block scope of node in which this variable was declared with `let` kind', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`
@@ -140,7 +82,106 @@ describe('VariableDeclarationObfuscator', () => {
});
it('should not obfuscate variable call (`identifier` node) before variable declaration', () => {
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){5,6}\);/);
assert.match(obfuscationResult.getObfuscatedCode(), /console\['\\x6c\\x6f\\x67'\]\(_0x([a-z0-9]){4,6}\);/);
});
});
describe(`variable calls before variable declaration when function param has the same name as variables name`, () => {
let obfuscationResult: IObfuscationResult,
functionParamIdentifierName: string|null,
innerFunctionParamIdentifierName: string|null,
constructorIdentifierName: string|null,
objectIdentifierName: string|null,
variableDeclarationIdentifierName: string|null;
beforeEach(() => {
obfuscationResult = JavaScriptObfuscator.obfuscate(
`
(function () {
function foo (t, e) {
return function () {
function baz (t) {
console.log(t);
}
return {t: t};
var t;
}();
}
})();
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
});
it('should correct obfuscate variables inside function body', () => {
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
const functionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/function *_0x[a-z0-9]{4,6} *\((_0x[a-z0-9]{4,6})\,(_0x[a-z0-9]{4,6})\) *\{/);
const innerFunctionParamIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/function _0x[a-z0-9]{4,6} *\((_0x[a-z0-9]{4,6})\) *\{/);
const constructorIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/console\['\\x6c\\x6f\\x67'\]\((_0x[a-z0-9]{4,6})\)/);
const objectIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/return\{'\\x74':(_0x[a-z0-9]{4,6})\}/);
const variableDeclarationIdentifierMatch: RegExpMatchArray|null = obfuscatedCode
.match(/var *(_0x[a-z0-9]{4,6});/);
functionParamIdentifierName = (<RegExpMatchArray>functionParamIdentifierMatch)[1];
innerFunctionParamIdentifierName = (<RegExpMatchArray>innerFunctionParamIdentifierMatch)[1];
constructorIdentifierName = (<RegExpMatchArray>constructorIdentifierMatch)[1];
objectIdentifierName = (<RegExpMatchArray>objectIdentifierMatch)[1];
variableDeclarationIdentifierName = (<RegExpMatchArray>variableDeclarationIdentifierMatch)[1];
assert.notEqual(functionParamIdentifierName, constructorIdentifierName);
assert.notEqual(functionParamIdentifierName, innerFunctionParamIdentifierName);
assert.equal(functionParamIdentifierName, objectIdentifierName);
assert.equal(functionParamIdentifierName, variableDeclarationIdentifierName);
assert.equal(innerFunctionParamIdentifierName, constructorIdentifierName);
assert.equal(variableDeclarationIdentifierName, objectIdentifierName);
});
});
describe('wrong replacement', () => {
it('shouldn\'t replace property node identifier', () => {
let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
`
function foo () {
var test = 'abc';
var object = {
test: 'cde'
};
console.log(test);
}
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
assert.match(obfuscationResult.getObfuscatedCode(), /var _0x([a-z0-9]){4,6} *= *\{'\\x74\\x65\\x73\\x74/);
});
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);
}
`,
Object.assign({}, NO_CUSTOM_NODES_PRESET)
);
assert.match(obfuscationResult.getObfuscatedCode(), /_0x([a-z0-9]){4,6}\['\\x74\\x65\\x73\\x74'\]/);
});
});
});
@@ -0,0 +1,427 @@
import * as chai from 'chai';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TNodeWithBlockStatement } from '../../../src/types/TNodeWithBlockStatement';
import { IStackTraceData } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceData';
import { readFileAsString } from '../../helpers/readFileAsString';
import { Nodes } from '../../../src/Nodes';
import { NodeMocks } from '../../mocks/NodeMocks';
import { NodeUtils } from '../../../src/NodeUtils';
import { StackTraceAnalyzer } from '../../../src/stack-trace-analyzer/StackTraceAnalyzer';
const assert: any = chai.assert;
/**
* @param astTree
* @param name
* @returns {ESTree.FunctionDeclaration|null}
*/
function getFunctionDeclarationByName (astTree: ESTree.Node, name: string): ESTree.FunctionDeclaration|null {
let functionDeclarationNode: ESTree.FunctionDeclaration|null = null;
estraverse.traverse(astTree, {
enter: (node: ESTree.Node): any => {
if (
Nodes.isFunctionDeclarationNode(node) &&
Nodes.isIdentifierNode(node.id) &&
node.id.name === name
) {
functionDeclarationNode = node;
return estraverse.VisitorOption.Break;
}
}
});
return functionDeclarationNode;
}
/**
* @param astTree
* @param name
* @returns {ESTree.FunctionExpression|null}
*/
function getFunctionExpressionByName (astTree: ESTree.Node, name: string): ESTree.FunctionExpression|null {
let functionExpressionNode: ESTree.FunctionExpression|null = null;
estraverse.traverse(astTree, {
enter: (node: ESTree.Node): any => {
if (
Nodes.isVariableDeclaratorNode(node) &&
node.init &&
Nodes.isFunctionExpressionNode(node.init) &&
Nodes.isIdentifierNode(node.id) &&
node.id.name === name
) {
functionExpressionNode = node.init;
return estraverse.VisitorOption.Break;
}
}
});
return functionExpressionNode;
}
/**
* @param astTree
* @param id
* @returns {ESTree.FunctionExpression|null}
*/
function getFunctionExpressionById (astTree: ESTree.Node, id: string): ESTree.FunctionExpression|null {
let functionExpressionNode: ESTree.FunctionExpression|null = null;
estraverse.traverse(astTree, {
enter: (node: ESTree.Node): any => {
if (
Nodes.isFunctionExpressionNode(node) &&
node.id &&
Nodes.isIdentifierNode(node.id) &&
node.id.name === id
) {
functionExpressionNode = node;
return estraverse.VisitorOption.Break;
}
}
});
return functionExpressionNode;
}
/**
* @param astTree
* @param objectName
* @param name
* @returns {ESTree.FunctionExpression|null}
*/
function getObjectFunctionExpressionByName (astTree: ESTree.Node, objectName: string, name: string): ESTree.FunctionExpression|null {
let functionExpressionNode: ESTree.FunctionExpression|null = null,
targetObjectExpressionNode: ESTree.ObjectExpression|null = null;
estraverse.traverse(astTree, {
enter: (node: ESTree.Node): any => {
if (
Nodes.isVariableDeclaratorNode(node) &&
Nodes.isIdentifierNode(node.id) &&
node.init &&
Nodes.isObjectExpressionNode(node.init) &&
node.id.name === objectName
) {
targetObjectExpressionNode = node.init;
return estraverse.VisitorOption.Break;
}
}
});
if (!targetObjectExpressionNode) {
return null;
}
estraverse.traverse(targetObjectExpressionNode, {
enter: (node: ESTree.Node): any => {
if (
Nodes.isPropertyNode(node) &&
Nodes.isFunctionExpressionNode(node.value) &&
(
(Nodes.isIdentifierNode(node.key) && node.key.name === name) ||
(Nodes.isLiteralNode(node.key) && node.key.value === name)
)
) {
functionExpressionNode = node.value;
return estraverse.VisitorOption.Break;
}
}
});
return functionExpressionNode;
}
describe('StackTraceAnalyzer', () => {
describe('extract (): IStackTraceData[]', () => {
let astTree: TNodeWithBlockStatement,
stackTraceData: IStackTraceData[],
expectedStackTraceData: IStackTraceData[];
it('should returns correct IStackTraceData - variant #1: basic-1', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/basic-1.js')
)
);
expectedStackTraceData = [
{
name: 'baz',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'baz')).body,
stackTrace: []
},
{
name: 'foo',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'foo')).body,
stackTrace: []
},
{
name: 'bar',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
stackTrace: [
{
name: 'inner2',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner2')).body,
stackTrace: [
{
name: 'inner3',
callee: (<ESTree.FunctionExpression>getFunctionExpressionByName(astTree, 'inner3')).body,
stackTrace: []
},
]
},
{
name: 'inner1',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
stackTrace: []
},
]
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #2: basic-2', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/basic-2.js')
)
);
expectedStackTraceData = [
{
name: 'bar',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
stackTrace: []
},
{
name: 'baz',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'baz')).body,
stackTrace: [
{
name: 'inner1',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
stackTrace: []
},
]
},
{
name: 'foo',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'foo')).body,
stackTrace: []
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #3: deep conditions nesting', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/deep-conditions-nesting.js')
)
);
expectedStackTraceData = [
{
name: 'bar',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
stackTrace: []
},
{
name: 'baz',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'baz')).body,
stackTrace: [
{
name: 'inner1',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
stackTrace: []
},
]
},
{
name: 'foo',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'foo')).body,
stackTrace: []
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #4: call before declaration', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/call-before-declaration.js')
)
);
expectedStackTraceData = [
{
name: 'bar',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'bar')).body,
stackTrace: []
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #5: call expression of object member', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/call-expression-of-object-member.js')
)
);
expectedStackTraceData = [
{
name: 'baz',
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'baz')).body,
stackTrace: []
},
{
name: 'baz',
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'baz')).body,
stackTrace: []
},
{
name: 'func',
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'func')).body,
stackTrace: []
},
{
name: 'bar',
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object1', 'bar')).body,
stackTrace: [
{
name: 'inner1',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner1')).body,
stackTrace: [
]
},
]
},
{
name: 'bar',
callee: (<ESTree.FunctionExpression>getObjectFunctionExpressionByName(astTree, 'object', 'bar')).body,
stackTrace: [
{
name: 'inner',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner')).body,
stackTrace: [
]
},
]
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #6: no call expressions', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/no-call-expressions.js')
)
);
expectedStackTraceData = [];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #7: only call expression', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/only-call-expression.js')
)
);
expectedStackTraceData = [];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #8: self-invoking functions', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/self-invoking-functions.js')
)
);
expectedStackTraceData = [
{
name: null,
callee: (<ESTree.FunctionExpression>getFunctionExpressionById(astTree, 'foo')).body,
stackTrace: [{
name: null,
callee: (<ESTree.FunctionExpression>getFunctionExpressionById(astTree, 'bar')).body,
stackTrace: [{
name: null,
callee: (<ESTree.FunctionExpression>getFunctionExpressionById(astTree, 'baz')).body,
stackTrace: [{
name: 'inner',
callee: (<ESTree.FunctionDeclaration>getFunctionDeclarationByName(astTree, 'inner')).body,
stackTrace: []
}]
}]
}]
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
it('should returns correct BlockScopeTraceData - variant #9: no recursion', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/stack-trace-analyzer/no-recursion.js')
)
);
expectedStackTraceData = [
{
name: 'bar',
callee: (<ESTree.FunctionExpression>getFunctionExpressionByName(astTree, 'bar')).body,
stackTrace: []
}
];
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
assert.deepEqual(stackTraceData, expectedStackTraceData);
});
});
});
@@ -0,0 +1,94 @@
import 'format-unicorn';
import { DomainLockNodeTemplate } from '../../../../../src/templates/custom-nodes/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
import { Utils } from '../../../../../src/Utils';
const assert: Chai.AssertStatic = require('chai').assert;
/**
* @param templateData
* @param callsControllerFunctionName
* @param currentDomain
* @returns {Function}
*/
function getFunctionFromTemplate (templateData: any, callsControllerFunctionName: string, currentDomain: string) {
let domainLockTemplate: string = DomainLockNodeTemplate().formatUnicorn(templateData);
return Function(`
document = {
domain: '${currentDomain}'
};
var ${callsControllerFunctionName} = (function(){
return function (context, fn){
return function () {
return fn.apply(context, arguments);
};
}
})();
${domainLockTemplate}
`)();
}
describe('DomainLockNodeTemplate (): string', () => {
let domainsString: string,
currentDomain: string,
hiddenDomainsString: string,
diff: string,
singleNodeCallControllerFunctionName: string = 'callsController';
it('should correctly runs code inside template if current domain matches with `domainsString`', () => {
domainsString = ['www.example.com'].join(';');
currentDomain = 'www.example.com';
[
hiddenDomainsString,
diff
] = Utils.hideString(domainsString, domainsString.length * 3);
assert.doesNotThrow(() => getFunctionFromTemplate({
domainLockFunctionName: 'domainLockFunction',
diff: diff,
domains: hiddenDomainsString,
singleNodeCallControllerFunctionName
}, singleNodeCallControllerFunctionName, currentDomain));
});
it('should correctly runs code inside template if current domain matches with base domain of `domainsString` item', () => {
domainsString = ['www.test.com', '.example.com'].join(';');
currentDomain = 'subdomain.example.com';
[
hiddenDomainsString,
diff
] = Utils.hideString(domainsString, domainsString.length * 3);
assert.doesNotThrow(() => getFunctionFromTemplate({
domainLockFunctionName: 'domainLockFunction',
diff: diff,
domains: hiddenDomainsString,
singleNodeCallControllerFunctionName
}, singleNodeCallControllerFunctionName, currentDomain));
});
it('should throw an error if current domain doesn\'t match with `domainsString`', () => {
domainsString = ['www.example.com'].join(';');
currentDomain = 'www.test.com';
[
hiddenDomainsString,
diff
] = Utils.hideString(domainsString, domainsString.length * 3);
assert.throws(() => getFunctionFromTemplate({
domainLockFunctionName: 'domainLockFunction',
diff: diff,
domains: hiddenDomainsString,
singleNodeCallControllerFunctionName
}, singleNodeCallControllerFunctionName, currentDomain));
});
afterEach(() => {
delete (<any>global).promisePolyfillActivationFlag;
});
});
@@ -0,0 +1,93 @@
import 'format-unicorn';
import { AtobTemplate } from '../../../../../src/templates/custom-nodes/AtobTemplate';
import { Rc4Template } from '../../../../../src/templates/custom-nodes/Rc4Template';
import { UnicodeArrayBase64DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/unicode-array-nodes/unicode-array-calls-wrapper/UnicodeArrayBase64DecodeNodeTemplate';
import { UnicodeArrayCallsWrapperTemplate } from '../../../../../src/templates/custom-nodes/unicode-array-nodes/unicode-array-calls-wrapper/UnicodeArrayCallsWrapperTemplate';
import { UnicodeArrayRc4DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/unicode-array-nodes/unicode-array-calls-wrapper/UnicodeArrayRC4DecodeNodeTemplate';
import { Utils } from '../../../../../src/Utils';
const assert: Chai.AssertStatic = require('chai').assert;
/**
* @param templateData
* @param unicodeArrayName
* @param unicodeArrayCallsWrapperName
* @param index
* @returns {Function}
*/
function getFunctionFromTemplateBase64Encoding (
templateData: any,
unicodeArrayName: string,
unicodeArrayCallsWrapperName: string,
index: string
) {
let unicodeArrayCallsWrapperTemplate: string = UnicodeArrayCallsWrapperTemplate().formatUnicorn(templateData);
return Function(`
var ${unicodeArrayName} = ['${Utils.btoa('test1')}'];
${unicodeArrayCallsWrapperTemplate}
return ${unicodeArrayCallsWrapperName}(${index});
`)();
}
/**
* @param templateData
* @param unicodeArrayName
* @param unicodeArrayCallsWrapperName
* @param index
* @param key
* @returns {Function}
*/
function getFunctionFromTemplateRc4Encoding (
templateData: any,
unicodeArrayName: string,
unicodeArrayCallsWrapperName: string,
index: string,
key: string
) {
let unicodeArrayCallsWrapperTemplate: string = UnicodeArrayCallsWrapperTemplate().formatUnicorn(templateData);
return Function(`
var ${unicodeArrayName} = ['${Utils.btoa(Utils.rc4('test1', key))}'];
${unicodeArrayCallsWrapperTemplate}
return ${unicodeArrayCallsWrapperName}('${index}', '${key}');
`)();
}
describe('UnicodeArrayCallsWrapperNodeTemplate (): string', () => {
let unicodeArrayName: string = 'unicodeArrayName',
unicodeArrayCallsWrapperName: string = 'unicodeArrayCallsWrapperName',
atobDecodeNodeTemplate: string = UnicodeArrayBase64DecodeNodeTemplate().formatUnicorn({
atobPolyfill: AtobTemplate(),
selfDefendingCode: '',
unicodeArrayCallsWrapperName
}),
rc4DecodeNodeTemplate: string = UnicodeArrayRc4DecodeNodeTemplate().formatUnicorn({
atobPolyfill: AtobTemplate(),
rc4Polyfill: Rc4Template(),
selfDefendingCode: '',
unicodeArrayCallsWrapperName
});
it('should correctly returns decoded value with base64 encoding', () => {
assert.deepEqual(getFunctionFromTemplateBase64Encoding({
decodeNodeTemplate: atobDecodeNodeTemplate,
unicodeArrayCallsWrapperName,
unicodeArrayName
}, unicodeArrayName, unicodeArrayCallsWrapperName, '0x0'), 'test1');
});
it('should correctly returns decoded value with rc4 encoding', () => {
assert.deepEqual(getFunctionFromTemplateRc4Encoding({
decodeNodeTemplate: rc4DecodeNodeTemplate,
unicodeArrayCallsWrapperName,
unicodeArrayName
}, unicodeArrayName, unicodeArrayCallsWrapperName, '0x0', 'key'), 'test1');
});
});
+9
View File
@@ -0,0 +1,9 @@
import * as fs from 'fs';
/**
* @param path
* @returns {string}
*/
export function readFileAsString (path: string): string {
return fs.readFileSync(path, 'utf8');
}
+15
View File
@@ -7,6 +7,7 @@ BabelPolyfill.append();
/**
* Unit tests
*/
import './unit-tests/NodeAppender.spec';
import './unit-tests/NodeUtils.spec';
import './unit-tests/ObfuscationResult.spec';
import './unit-tests/OptionsNormalizer.spec';
@@ -16,6 +17,7 @@ import './unit-tests/cli/CLIUtils.spec';
import './unit-tests/node-obfuscators/CatchClauseObfuscator.spec';
import './unit-tests/node-obfuscators/FunctionDeclarationObfuscator.spec';
import './unit-tests/node-obfuscators/FunctionObfuscator.spec';
import './unit-tests/stack-trace-analyzer/StackTraceAnalyzer.spec';
/**
* Functional tests
@@ -23,9 +25,22 @@ import './unit-tests/node-obfuscators/FunctionObfuscator.spec';
import './functional-tests/JavaScriptObfuscator.spec';
import './functional-tests/JavaScriptObfuscatorCLI.spec';
import './functional-tests/JavaScriptObfuscatorInternal.spec';
import './functional-tests/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.spec';
import './functional-tests/custom-nodes/domain-lock-nodes/DomainLockNode.spec';
import './functional-tests/custom-nodes/unicode-array-nodes/UnicodeArrayCallsWrapper.spec';
import './functional-tests/custom-nodes/unicode-array-nodes/UnicodeArrayRotateFunctionNode.spec';
import './functional-tests/custom-nodes/unicode-array-nodes/UnicodeArrayNode.spec';
import './functional-tests/node-obfuscators/FunctionObfuscator.spec';
import './functional-tests/node-obfuscators/LiteralObfuscator.spec';
import './functional-tests/node-obfuscators/MemberExpressionObfuscator.spec';
import './functional-tests/node-obfuscators/MethodDefinitionObfuscator.spec';
import './functional-tests/node-obfuscators/ObjectExpressionObfuscator.spec';
import './functional-tests/node-obfuscators/VariableDeclarationObfuscator.spec';
import './functional-tests/stack-trace-analyzer/StackTraceAnalyzer.spec';
import './functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec';
import './functional-tests/templates/custom-nodes/unicode-array-nodes/UnicodeArrayCallsWrapperNodeTemplate.spec';
/**
* Performance tests
*/
import './performance-tests/JavaScriptObfuscatorPerformance.spec';
+36 -52
View File
@@ -1,30 +1,16 @@
import * as escodegen from 'escodegen';
import * as ESTree from 'estree';
import { TExpression } from "../../src/types/nodes/TExpression";
import { TStatement } from "../../src/types/nodes/TStatement";
import { TStatement } from '../../src/types/TStatement';
import { IBlockStatementNode } from "../../src/interfaces/nodes/IBlockStatementNode";
import { ICallExpressionNode } from "../../src/interfaces/nodes/ICallExpressionNode";
import { ICatchClauseNode } from "../../src/interfaces/nodes/ICatchClauseNode";
import { IExpressionStatementNode } from "../../src/interfaces/nodes/IExpressionStatementNode";
import { IFunctionDeclarationNode } from "../../src/interfaces/nodes/IFunctionDeclarationNode";
import { IIdentifierNode } from "../../src/interfaces/nodes/IIdentifierNode";
import { IIfStatementNode } from "../../src/interfaces/nodes/IIfStatementNode";
import { ILiteralNode } from "../../src/interfaces/nodes/ILiteralNode";
import { IMemberExpressionNode } from "../../src/interfaces/nodes/IMemberExpressionNode";
import { IProgramNode } from "../../src/interfaces/nodes/IProgramNode";
import { ISpreadElementNode } from "../../src/interfaces/nodes/ISpreadElementNode";
import { IVariableDeclarationNode } from "../../src/interfaces/nodes/IVariableDeclarationNode";
import { IVariableDeclaratorNode } from "../../src/interfaces/nodes/IVariableDeclaratorNode";
import { NodeType } from "../../src/enums/NodeType";
import { NodeType } from '../../src/enums/NodeType';
export class NodeMocks {
/**
* @param bodyNodes
* @returns {IProgramNode}
* @returns {ESTree.Program}
*/
public static getProgramNode (bodyNodes: TStatement[] = []): IProgramNode {
public static getProgramNode (bodyNodes: TStatement[] = []): ESTree.Program {
return {
type: NodeType.Program,
body: bodyNodes,
@@ -35,9 +21,9 @@ export class NodeMocks {
/**
* @param bodyNodes
* @returns {IBlockStatementNode}
* @returns {ESTree.BlockStatement}
*/
public static getBlockStatementNode (bodyNodes: TStatement[] = []): IBlockStatementNode {
public static getBlockStatementNode (bodyNodes: ESTree.Statement[] = []): ESTree.BlockStatement {
return {
type: NodeType.BlockStatement,
body: bodyNodes,
@@ -47,9 +33,9 @@ export class NodeMocks {
/**
* @param bodyNodes
* @returns {ICatchClauseNode}
* @returns {ESTree.CatchClause}
*/
public static getCatchClauseNode (bodyNodes: TStatement[] = []): ICatchClauseNode {
public static getCatchClauseNode (bodyNodes: ESTree.Statement[] = []): ESTree.CatchClause {
return {
type: NodeType.CatchClause,
param: NodeMocks.getIdentifierNode('err'),
@@ -61,12 +47,12 @@ export class NodeMocks {
/**
* @param callee
* @param args
* @returns {ICallExpressionNode}
* @returns {ESTree.CallExpression}
*/
public static getCallExpressionNode (
callee: TExpression,
args: TExpression[] | ISpreadElementNode[] = []
): ICallExpressionNode {
callee: ESTree.Expression,
args: ESTree.Expression[] | ESTree.SpreadElement[] = []
): ESTree.CallExpression {
return {
type: NodeType.CallExpression,
callee: callee,
@@ -77,11 +63,11 @@ export class NodeMocks {
/**
* @param expression
* @returns {IExpressionStatementNode}
* @returns {ESTree.ExpressionStatement}
*/
public static getExpressionStatementNode (
expression: TExpression = NodeMocks.getIdentifierNode()
): IExpressionStatementNode {
expression: ESTree.Expression = NodeMocks.getIdentifierNode()
): ESTree.ExpressionStatement {
return {
type: NodeType.ExpressionStatement,
expression: expression,
@@ -93,29 +79,28 @@ export class NodeMocks {
* @param functionName
* @param blockStatementNode
* @param params
* @returns {IFunctionDeclarationNode}
* @returns {ESTree.FunctionDeclaration}
*/
public static getFunctionDeclarationNode (
functionName: string,
blockStatementNode: IBlockStatementNode,
params: IIdentifierNode[] = []
): IFunctionDeclarationNode {
blockStatementNode: ESTree.BlockStatement,
params: ESTree.Identifier[] = []
): ESTree.FunctionDeclaration {
return {
type: NodeType.FunctionDeclaration,
id: NodeMocks.getIdentifierNode(functionName),
params: params,
body: blockStatementNode,
generator: false,
expression: false,
obfuscated: false
};
}
/**
* @param blockStatementNode
* @returns {IIfStatementNode}
* @returns {ESTree.IfStatement}
*/
public static getIfStatementNode (blockStatementNode: IBlockStatementNode): IIfStatementNode {
public static getIfStatementNode (blockStatementNode: ESTree.BlockStatement): ESTree.IfStatement {
return {
type: 'IfStatement',
test: {
@@ -125,16 +110,15 @@ export class NodeMocks {
obfuscated: false
},
consequent: blockStatementNode,
alternate: null,
obfuscated: false
};
}
/**
* @param identifierName
* @returns {IIdentifierNode}
* @returns {ESTree.Identifier}
*/
public static getIdentifierNode (identifierName: string = 'identifier'): IIdentifierNode {
public static getIdentifierNode (identifierName: string = 'identifier'): ESTree.Identifier {
return {
type: NodeType.Identifier,
name: identifierName,
@@ -144,9 +128,9 @@ export class NodeMocks {
/**
* @param value
* @returns {ILiteralNode}
* @returns {ESTree.Literal}
*/
public static getLiteralNode (value: boolean|number|string = 'value'): ILiteralNode {
public static getLiteralNode (value: boolean|number|string = 'value'): ESTree.Literal {
return {
type: NodeType.Literal,
value: value,
@@ -162,12 +146,12 @@ export class NodeMocks {
/**
* @param object
* @param property
* @return {IMemberExpressionNode}
* @return {ESTree.MemberExpression}
*/
public static getMemberExpressionNode (
object: IIdentifierNode,
property: IIdentifierNode|ILiteralNode
): IMemberExpressionNode {
object: ESTree.Identifier,
property: ESTree.Identifier|ESTree.Literal
): ESTree.MemberExpression {
return {
type: NodeType.MemberExpression,
computed: false,
@@ -180,12 +164,12 @@ export class NodeMocks {
/**
* @param declarations
* @param kind
* @returns {IVariableDeclarationNode}
* @returns {ESTree.VariableDeclaration}
*/
public static getVariableDeclarationNode (
declarations: IVariableDeclaratorNode[] = [],
kind: string = 'var'
): IVariableDeclarationNode {
declarations: ESTree.VariableDeclarator[] = [],
kind: 'var' | 'let' | 'const' = 'var'
): ESTree.VariableDeclaration {
return {
type: NodeType.VariableDeclaration,
declarations: declarations,
@@ -197,9 +181,9 @@ export class NodeMocks {
/**
* @param id
* @param init
* @returns {IVariableDeclaratorNode}
* @returns {ESTree.VariableDeclarator}
*/
public static getVariableDeclaratorNode (id: IIdentifierNode, init: any): IVariableDeclaratorNode {
public static getVariableDeclaratorNode (id: ESTree.Identifier, init: any): ESTree.VariableDeclarator {
return {
type: NodeType.VariableDeclarator,
id: id,
@@ -0,0 +1,31 @@
import { readFileAsString } from '../helpers/readFileAsString';
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscator';
const assert: Chai.AssertStatic = require('chai').assert;
describe('JavaScriptObfuscator performance', () => {
const iterationsCount: number = 500;
describe('performance: multiple calls', () => {
it('shows performance time with multiple obfuscator calls', function (): void {
this.timeout(100000);
for (let i: number = 0; i < iterationsCount; i++) {
JavaScriptObfuscator.obfuscate(readFileAsString('./test/fixtures/sample.js'));
}
assert.isOk(true);
});
});
describe('performance: large source code', () => {
it('shows performance time with large code size', function (): void {
this.timeout(100000);
JavaScriptObfuscator.obfuscate(readFileAsString('./test/fixtures/sample.js').repeat(iterationsCount));
assert.isOk(true);
});
});
});
+244
View File
@@ -0,0 +1,244 @@
import * as chai from 'chai';
import * as ESTree from 'estree';
import { TStatement } from '../../src/types/TStatement';
import { IStackTraceData } from '../../src/interfaces/stack-trace-analyzer/IStackTraceData';
import { readFileAsString } from '../helpers/readFileAsString';
import { NodeAppender } from '../../src/NodeAppender';
import { NodeMocks } from '../mocks/NodeMocks';
import { NodeUtils } from '../../src/NodeUtils';
import { StackTraceAnalyzer } from '../../src/stack-trace-analyzer/StackTraceAnalyzer';
const assert: any = chai.assert;
describe('NodeAppender', () => {
describe('appendNode (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[]): void', () => {
let astTree: ESTree.Program,
expectedAstTree: ESTree.Program,
node: TStatement[];
beforeEach(() => {
node = NodeUtils.convertCodeToStructure(`
var test = 1;
`);
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node.js')
)
);
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-expected.js')
)
);
NodeUtils.parentize(astTree);
NodeUtils.parentize(expectedAstTree);
NodeAppender.appendNode(astTree, node);
});
it('should append given node to a `BlockStatement` node body', () => {
assert.deepEqual(astTree, expectedAstTree);
});
});
describe('appendNodeToOptimalBlockScope (blockScopeStackTraceData: IStackTraceData[], blockScopeNode: TNodeWithBlockStatement, nodeBodyStatements: TStatement[], index: number = 0): void', () => {
let astTree: ESTree.Program,
expectedAstTree: ESTree.Program,
node: TStatement[],
stackTraceData: IStackTraceData[];
beforeEach(() => {
node = NodeUtils.convertCodeToStructure(`
var test = 1;
`);
});
it('should append node into first and deepest function call in calls trace - variant #1', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-1.js')
)
);
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-1-expected.js')
)
);
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node);
assert.deepEqual(astTree, expectedAstTree);
});
it('should append node into first and deepest function call in calls trace - variant #2', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-2.js')
)
);
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/variant-2-expected.js')
)
);
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node);
assert.deepEqual(astTree, expectedAstTree);
});
describe('append by specific index', () => {
let astTree: ESTree.Program;
beforeEach(() => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index.js')
)
);
});
it('should append node into deepest function call by specified index in calls trace - variant #1', () => {
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-1-expected.js')
)
);
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node, 2);
assert.deepEqual(astTree, expectedAstTree);
});
it('should append node into deepest function call by specified index in calls trace - variant #2', () => {
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-2-expected.js')
)
);
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
NodeAppender.appendNodeToOptimalBlockScope(stackTraceData, astTree, node, 1);
assert.deepEqual(astTree, expectedAstTree);
});
it('should append node into deepest function call by specified index in calls trace - variant #3', () => {
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-3.js')
)
);
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/append-node-to-optimal-block-scope/by-index-variant-3-expected.js')
)
);
stackTraceData = new StackTraceAnalyzer(astTree.body).analyze();
NodeAppender.appendNodeToOptimalBlockScope(
stackTraceData,
astTree,
node,
NodeAppender.getRandomStackTraceIndex(stackTraceData.length)
);
assert.deepEqual(astTree, expectedAstTree);
});
});
});
describe('getRandomStackTraceIndex (stackTraceRootLength: number): number', () => {
it('should returns random index between 0 and stack trace data root length', () => {
let index: number;
for (let i: number = 0; i < 100; i++) {
index = NodeAppender.getRandomStackTraceIndex(100);
assert.isAtLeast(index, 0);
assert.isAtMost(index, 100);
}
});
});
describe('insertNodeAtIndex (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[], index: number): void', () => {
let astTree: ESTree.Program,
expectedAstTree: ESTree.Program,
node: TStatement[];
beforeEach(() => {
node = NodeUtils.convertCodeToStructure(`
var test = 1;
`);
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/insert-node-at-index.js')
)
);
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/insert-node-at-index-expected.js')
)
);
NodeUtils.parentize(astTree);
NodeUtils.parentize(expectedAstTree);
NodeAppender.insertNodeAtIndex(astTree, node, 2);
});
it('should insert given node in `BlockStatement` node body at index', () => {
assert.deepEqual(astTree, expectedAstTree);
});
});
describe('prependNode (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[]): void', () => {
let astTree: ESTree.Program,
expectedAstTree: ESTree.Program,
node: TStatement[];
beforeEach(() => {
node = NodeUtils.convertCodeToStructure(`
var test = 1;
`);
astTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/prepend-node.js')
)
);
expectedAstTree = NodeMocks.getProgramNode(
NodeUtils.convertCodeToStructure(
readFileAsString('./test/fixtures/node-appender/prepend-node-expected.js')
)
);
NodeUtils.parentize(astTree);
NodeUtils.parentize(expectedAstTree);
NodeAppender.prependNode(astTree, node);
});
it('should prepend given node to a `BlockStatement` node body', () => {
assert.deepEqual(astTree, expectedAstTree);
});
});
});
+31 -141
View File
@@ -1,15 +1,5 @@
import * as chai from 'chai';
import { IBlockStatementNode } from "../../src/interfaces/nodes/IBlockStatementNode";
import { IExpressionStatementNode } from "../../src/interfaces/nodes/IExpressionStatementNode";
import { IFunctionDeclarationNode } from "../../src/interfaces/nodes/IFunctionDeclarationNode";
import { IIdentifierNode } from "../../src/interfaces/nodes/IIdentifierNode";
import { IIfStatementNode } from "../../src/interfaces/nodes/IIfStatementNode";
import { ILiteralNode } from "../../src/interfaces/nodes/ILiteralNode";
import { INode } from "../../src/interfaces/nodes/INode";
import { IProgramNode } from "../../src/interfaces/nodes/IProgramNode";
import { IVariableDeclarationNode } from "../../src/interfaces/nodes/IVariableDeclarationNode";
import { IVariableDeclaratorNode } from "../../src/interfaces/nodes/IVariableDeclaratorNode";
import * as ESTree from 'estree';
import { NodeMocks } from '../mocks/NodeMocks';
import { NodeUtils } from '../../src/NodeUtils';
@@ -17,7 +7,7 @@ import { NodeUtils } from '../../src/NodeUtils';
const assert: any = chai.assert;
describe('NodeUtils', () => {
describe('addXVerbatimPropertyToLiterals (node: INode): void', () => {
describe('addXVerbatimPropertyToLiterals (node: ESTree.Node): void', () => {
let literalNode: any,
expectedLiteralNode: any;
@@ -35,43 +25,13 @@ describe('NodeUtils', () => {
});
});
describe('appendNode (blockScopeBody: INode[], node: INode): void', () => {
let blockStatementNode: IBlockStatementNode,
expectedBlockStatementNode: IBlockStatementNode,
expressionStatementNode: IExpressionStatementNode;
beforeEach(() => {
expressionStatementNode = NodeMocks.getExpressionStatementNode();
blockStatementNode = NodeMocks.getBlockStatementNode();
expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
expressionStatementNode
]);
NodeUtils.appendNode(blockStatementNode.body, expressionStatementNode);
});
it('should append given node to a `BlockStatement` node body', () => {
assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
});
it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
assert.doesNotChange(
() => NodeUtils.appendNode(blockStatementNode.body, <INode>{}),
blockStatementNode,
'body'
);
});
});
describe('convertCodeToStructure (code: string): INode', () => {
describe('convertCodeToStructure (code: string): ESTree.Node[]', () => {
let code: string,
identifierNode: IIdentifierNode,
literalNode: ILiteralNode,
programNode: IProgramNode,
variableDeclarationNode: IVariableDeclarationNode,
variableDeclaratorNode: IVariableDeclaratorNode;
identifierNode: ESTree.Identifier,
literalNode: ESTree.Literal,
programNode: ESTree.Program,
variableDeclarationNode: ESTree.VariableDeclaration,
variableDeclaratorNode: ESTree.VariableDeclarator;
beforeEach(() => {
code = `
@@ -99,15 +59,15 @@ describe('NodeUtils', () => {
literalNode['parentNode'] = variableDeclaratorNode;
});
it('should convert code to `INode` structure', () => {
assert.deepEqual(NodeUtils.convertCodeToStructure(code), variableDeclarationNode);
it('should convert code to `ESTree.Node[]` structure array', () => {
assert.deepEqual(NodeUtils.convertCodeToStructure(code), [variableDeclarationNode]);
});
});
describe('getBlockStatementNodeByIndex (node: INode, index: number = 0): INode', () => {
let blockStatementNode: IBlockStatementNode,
expressionStatementNode1: IExpressionStatementNode,
expressionStatementNode2: IExpressionStatementNode;
describe('getBlockStatementNodeByIndex (node: ESTree.Node, index: number = 0): ESTree.Node', () => {
let blockStatementNode: ESTree.BlockStatement,
expressionStatementNode1: ESTree.ExpressionStatement,
expressionStatementNode2: ESTree.ExpressionStatement;
beforeEach(() => {
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
@@ -133,17 +93,17 @@ describe('NodeUtils', () => {
});
});
describe('getBlockScopeOfNode (node: INode, depth: number = 0): TNodeWithBlockStatement', () => {
let functionDeclarationBlockStatementNode: IBlockStatementNode,
ifStatementBlockStatementNode1: IBlockStatementNode,
ifStatementBlockStatementNode2: IBlockStatementNode,
ifStatementNode1: IIfStatementNode,
ifStatementNode2: IIfStatementNode,
expressionStatementNode1: IExpressionStatementNode,
expressionStatementNode2: IExpressionStatementNode,
expressionStatementNode3: IExpressionStatementNode,
functionDeclarationNode: IFunctionDeclarationNode,
programNode: IProgramNode;
describe('getBlockScopeOfNode (node: ESTree.Node, depth: number = 0): TNodeWithBlockStatement', () => {
let functionDeclarationBlockStatementNode: ESTree.BlockStatement,
ifStatementBlockStatementNode1: ESTree.BlockStatement,
ifStatementBlockStatementNode2: ESTree.BlockStatement,
ifStatementNode1: ESTree.IfStatement,
ifStatementNode2: ESTree.IfStatement,
expressionStatementNode1: ESTree.ExpressionStatement,
expressionStatementNode2: ESTree.ExpressionStatement,
expressionStatementNode3: ESTree.ExpressionStatement,
functionDeclarationNode: ESTree.FunctionDeclaration,
programNode: ESTree.Program;
beforeEach(() => {
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
@@ -199,47 +159,12 @@ describe('NodeUtils', () => {
});
});
describe('insertNodeAtIndex (blockScopeBody: INode[], node: INode, index: number): void', () => {
let blockStatementNode: IBlockStatementNode,
expectedBlockStatementNode: IBlockStatementNode,
expressionStatementNode1: IExpressionStatementNode,
expressionStatementNode2: IExpressionStatementNode;
beforeEach(() => {
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
blockStatementNode = NodeMocks.getBlockStatementNode([
expressionStatementNode1
]);
expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
expressionStatementNode1,
expressionStatementNode1
]);
NodeUtils.insertNodeAtIndex(blockStatementNode.body, expressionStatementNode2, 1);
});
it('should insert given node in `BlockStatement` node body at index', () => {
assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
});
it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
assert.doesNotChange(
() => NodeUtils.insertNodeAtIndex(blockStatementNode.body, <INode>{}, 1),
blockStatementNode,
'body'
);
});
});
describe('parentize (node: INode): void', () => {
let ifStatementNode: IIfStatementNode,
ifStatementBlockStatementNode: IBlockStatementNode,
expressionStatementNode1: IExpressionStatementNode,
expressionStatementNode2: IExpressionStatementNode,
programNode: IProgramNode;
describe('parentize (node: ESTree.Node): void', () => {
let ifStatementNode: ESTree.IfStatement,
ifStatementBlockStatementNode: ESTree.BlockStatement,
expressionStatementNode1: ESTree.ExpressionStatement,
expressionStatementNode2: ESTree.ExpressionStatement,
programNode: ESTree.Program;
beforeEach(() => {
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
@@ -281,39 +206,4 @@ describe('NodeUtils', () => {
assert.deepEqual(expressionStatementNode2['parentNode'], ifStatementBlockStatementNode);
});
});
describe('prependNode (blockScopeBody: INode[], node: INode): void', () => {
let blockStatementNode: IBlockStatementNode,
expectedBlockStatementNode: IBlockStatementNode,
expressionStatementNode1: IExpressionStatementNode,
expressionStatementNode2: IExpressionStatementNode;
beforeEach(() => {
expressionStatementNode1 = NodeMocks.getExpressionStatementNode();
expressionStatementNode2 = NodeMocks.getExpressionStatementNode();
blockStatementNode = NodeMocks.getBlockStatementNode([
expressionStatementNode1
]);
expectedBlockStatementNode = NodeMocks.getBlockStatementNode([
expressionStatementNode2,
expressionStatementNode1
]);
NodeUtils.prependNode(blockStatementNode.body, expressionStatementNode2);
});
it('should prepend given node to a `BlockStatement` node body', () => {
assert.deepEqual(blockStatementNode, expectedBlockStatementNode);
});
it('should does not change `BlockStatement` node body if given node is not a valid Node', () => {
assert.doesNotChange(
() => NodeUtils.prependNode(blockStatementNode.body, <INode>{}),
blockStatementNode,
'body'
);
});
});
});
+2 -2
View File
@@ -1,6 +1,6 @@
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
import { ObfuscationResult } from "../../src/ObfuscationResult";
import { ObfuscationResult } from '../../src/ObfuscationResult';
const assert: Chai.AssertStatic = require('chai').assert;
+21 -15
View File
@@ -1,9 +1,9 @@
import { IObfuscatorOptions } from "../../src/interfaces/IObfuscatorOptions";
import { IOptions } from "../../src/interfaces/IOptions";
import { IObfuscatorOptions } from '../../src/interfaces/IObfuscatorOptions';
import { IOptions } from '../../src/interfaces/IOptions';
import { DEFAULT_PRESET } from '../../src/preset-options/DefaultPreset';
import { Options } from "../../src/options/Options";
import { Options } from '../../src/options/Options';
import { OptionsNormalizer } from '../../src/options/OptionsNormalizer';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -24,39 +24,45 @@ describe('OptionsNormalizer', () => {
optionsPreset1 = Object.assign({}, DEFAULT_PRESET, {
compact: false,
rotateUnicodeArray: true,
sourceMapBaseUrl: 'http://localhost:9000',
unicodeArray: false,
unicodeArrayThreshold: 0.5,
wrapUnicodeArrayCalls: true
unicodeArrayEncoding: 'rc4',
unicodeArrayThreshold: 0.5
});
optionsPreset2 = Object.assign({}, DEFAULT_PRESET, {
rotateUnicodeArray: true,
sourceMapBaseUrl: 'http://localhost:9000',
sourceMapFileName: '//outputSourceMapName',
unicodeArray: true,
unicodeArrayThreshold: 0,
wrapUnicodeArrayCalls: true
unicodeArrayThreshold: 0
});
optionsPreset3 = Object.assign({}, DEFAULT_PRESET, {
domainLock: ['//localhost:9000', 'https://google.ru/abc?cde=fgh'],
sourceMapFileName: '/outputSourceMapName.map',
unicodeArray: true,
encodeUnicodeLiterals: true,
wrapUnicodeArrayCalls: false
unicodeArrayEncoding: true
});
expectedOptionsPreset1 = Object.assign({}, DEFAULT_PRESET, {
compact: true,
rotateUnicodeArray: false,
sourceMapBaseUrl: '',
unicodeArray: false,
unicodeArrayThreshold: 0,
wrapUnicodeArrayCalls: false
unicodeArrayEncoding: false,
unicodeArrayThreshold: 0
});
expectedOptionsPreset2 = Object.assign({}, DEFAULT_PRESET, {
rotateUnicodeArray: false,
sourceMapBaseUrl: 'http://localhost:9000/',
sourceMapFileName: 'outputSourceMapName.js.map',
unicodeArray: false,
unicodeArrayThreshold: 0,
wrapUnicodeArrayCalls: false
unicodeArrayThreshold: 0
});
expectedOptionsPreset3 = Object.assign({}, DEFAULT_PRESET, {
domainLock: ['localhost', 'google.ru'],
sourceMapFileName: 'outputSourceMapName.js.map',
unicodeArray: true,
encodeUnicodeLiterals: true,
wrapUnicodeArrayCalls: true
unicodeArrayEncoding: 'base64'
});
options1 = new Options(optionsPreset1);
+6 -10
View File
@@ -1,12 +1,12 @@
import { IObfuscationResult } from "../../src/interfaces/IObfuscationResult";
import { ISourceMapCorrector } from "../../src/interfaces/ISourceMapCorrector";
import { IObfuscationResult } from '../../src/interfaces/IObfuscationResult';
import { ISourceMapCorrector } from '../../src/interfaces/ISourceMapCorrector';
import { TSourceMapMode } from "../../src/types/TSourceMapMode";
import { TSourceMapMode } from '../../src/types/TSourceMapMode';
import { SourceMapMode } from "../../src/enums/SourceMapMode";
import { SourceMapMode } from '../../src/enums/SourceMapMode';
import { ObfuscationResult } from "../../src/ObfuscationResult";
import { SourceMapCorrector } from "../../src/SourceMapCorrector";
import { ObfuscationResult } from '../../src/ObfuscationResult';
import { SourceMapCorrector } from '../../src/SourceMapCorrector';
const assert: Chai.AssertStatic = require('chai').assert;
@@ -57,10 +57,6 @@ describe('SourceMapCorrector', () => {
it('should add source map to obfuscated code as base64 encoded string', () => {
assert.match(expectedObfuscationResult.getObfuscatedCode(), /data:application\/json;base64/);
});
it('should clear original source map', () => {
assert.equal(expectedObfuscationResult.getSourceMap(), '');
});
});
it('should add source map import to obfuscated code if source map mode is `separate`', () => {
+21
View File
@@ -50,6 +50,16 @@ describe('Utils', () => {
});
});
describe('extractDomainFromUrl (url: string): string', () => {
it('should extract domain from the given URL', () => {
assert.equal(Utils.extractDomainFromUrl('http://google.ru'), 'google.ru');
assert.equal(Utils.extractDomainFromUrl('http://www.google.ru'), 'www.google.ru');
assert.equal(Utils.extractDomainFromUrl('https://www.google.ru:9000'), 'www.google.ru');
assert.equal(Utils.extractDomainFromUrl('//google.ru/abc'), 'google.ru');
assert.equal(Utils.extractDomainFromUrl('//localhost:9000'), 'localhost');
});
});
describe('getRandomVariableName (length: number = 6): string', () => {
it('should return a string of given length with random variable name', () => {
assert.match(Utils.getRandomVariableName(4), /^_0x(\w){4}$/);
@@ -80,4 +90,15 @@ describe('Utils', () => {
assert.equal(Utils.stringToUnicode('string'), expected);
});
});
describe('hideString (str: string, length: number): [string, string]', () => {
let original1: string = 'example.com',
[str1, diff] = Utils.hideString(original1, 30);
it('should return a string with the original string within', () => {
assert.isTrue(str1.length > original1.length);
assert.equal(str1.replace(new RegExp('[' + diff + ']', 'g'), ''), original1);
});
});
});
@@ -1,24 +1,24 @@
import { ICatchClauseNode } from "../../../src/interfaces/nodes/ICatchClauseNode";
import { ICustomNode } from "../../../src/interfaces/custom-nodes/ICustomNode";
import { IExpressionStatementNode } from "../../../src/interfaces/nodes/IExpressionStatementNode";
import * as ESTree from 'estree';
import { DEFAULT_PRESET } from "../../../src/preset-options/DefaultPreset";
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
import { NodeType } from "../../../src/enums/NodeType";
import { DEFAULT_PRESET } from '../../../src/preset-options/DefaultPreset';
import { NodeType } from '../../../src/enums/NodeType';
import { CatchClauseObfuscator } from '../../../src/node-obfuscators/CatchClauseObfuscator';
import { NodeMocks } from "../../mocks/NodeMocks";
import { Options } from "../../../src/options/Options";
import { NodeMocks } from '../../mocks/NodeMocks';
import { Options } from '../../../src/options/Options';
const assert: Chai.AssertStatic = require('chai').assert;
describe('CatchClauseObfuscator', () => {
describe('obfuscateNode (catchClauseNode: ICatchClauseNode): void', () => {
let catchClauseObfuscator: CatchClauseObfuscator,
catchClauseNode: ICatchClauseNode;
catchClauseNode: ESTree.CatchClause;
beforeEach(() => {
let expressionStatementNode: IExpressionStatementNode = {
let expressionStatementNode: ESTree.ExpressionStatement = {
type: NodeType.ExpressionStatement,
expression: {
type: NodeType.CallExpression,
@@ -64,7 +64,7 @@ describe('CatchClauseObfuscator', () => {
it('should obfuscate catch clause param calls in catch clause node body', () => {
assert.match(
catchClauseNode.param.name,
(<ESTree.Identifier>catchClauseNode.param).name,
/^_0x\w+$/
);
});
@@ -1,24 +1,22 @@
import { IBlockStatementNode } from "../../../src/interfaces/nodes/IBlockStatementNode";
import { ICustomNode } from "../../../src/interfaces/custom-nodes/ICustomNode";
import { IExpressionStatementNode } from "../../../src/interfaces/nodes/IExpressionStatementNode";
import { IFunctionDeclarationNode } from "../../../src/interfaces/nodes/IFunctionDeclarationNode";
import { IProgramNode } from "../../../src/interfaces/nodes/IProgramNode";
import * as ESTree from 'estree';
import { DEFAULT_PRESET } from "../../../src/preset-options/DefaultPreset";
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
import { DEFAULT_PRESET } from '../../../src/preset-options/DefaultPreset';
import { FunctionDeclarationObfuscator } from '../../../src/node-obfuscators/FunctionDeclarationObfuscator';
import { NodeMocks } from "../../mocks/NodeMocks";
import { Options } from "../../../src/options/Options";
import { NodeMocks } from '../../mocks/NodeMocks';
import { Options } from '../../../src/options/Options';
const assert: Chai.AssertStatic = require('chai').assert;
describe('FunctionDeclarationObfuscator', () => {
describe('obfuscateNode (functionDeclarationNode: IFunctionDeclarationNode, parentNode: INode): void', () => {
let expressionStatementNode: IExpressionStatementNode,
let expressionStatementNode: ESTree.ExpressionStatement,
functionDeclarationObfuscator: FunctionDeclarationObfuscator,
functionDeclarationNode: IFunctionDeclarationNode,
functionDeclarationNode: ESTree.FunctionDeclaration,
functionName: string = 'functionDeclaration',
programNode: IProgramNode;
programNode: ESTree.Program;
beforeEach(() => {
expressionStatementNode = NodeMocks.getExpressionStatementNode(
@@ -37,8 +35,8 @@ describe('FunctionDeclarationObfuscator', () => {
});
describe('if `functionDeclaration` node parent node is not a Program node', () => {
let blockStatementNode: IBlockStatementNode,
functionDeclarationParentNode: IFunctionDeclarationNode;
let blockStatementNode: ESTree.BlockStatement,
functionDeclarationParentNode: ESTree.FunctionDeclaration;
beforeEach(() => {
blockStatementNode = NodeMocks.getBlockStatementNode([
@@ -1,33 +1,30 @@
import { IBlockStatementNode } from "../../../src/interfaces/nodes/IBlockStatementNode";
import { ICustomNode } from "../../../src/interfaces/custom-nodes/ICustomNode";
import { IExpressionStatementNode } from "../../../src/interfaces/nodes/IExpressionStatementNode";
import { IFunctionDeclarationNode } from "../../../src/interfaces/nodes/IFunctionDeclarationNode";
import { IIdentifierNode } from "../../../src/interfaces/nodes/IIdentifierNode";
import { IProgramNode } from "../../../src/interfaces/nodes/IProgramNode";
import * as ESTree from 'estree';
import { DEFAULT_PRESET } from "../../../src/preset-options/DefaultPreset";
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
import { FunctionObfuscator } from "../../../src/node-obfuscators/FunctionObfuscator";
import { NodeMocks } from "../../mocks/NodeMocks";
import { Options } from "../../../src/options/Options";
import { DEFAULT_PRESET } from '../../../src/preset-options/DefaultPreset';
import { FunctionObfuscator } from '../../../src/node-obfuscators/FunctionObfuscator';
import { NodeMocks } from '../../mocks/NodeMocks';
import { Options } from '../../../src/options/Options';
const assert: Chai.AssertStatic = require('chai').assert;
describe('FunctionObfuscator', () => {
describe('obfuscateNode (functionNode: IFunctionNode): void', () => {
let blockStatementNode: IBlockStatementNode,
expressionStatementNode1: IExpressionStatementNode,
expressionStatementNode2: IExpressionStatementNode,
let blockStatementNode: ESTree.BlockStatement,
expressionStatementNode1: ESTree.ExpressionStatement,
expressionStatementNode2: ESTree.ExpressionStatement,
functionObfuscator: FunctionObfuscator,
functionDeclarationNode: IFunctionDeclarationNode,
functionDeclarationNode: ESTree.FunctionDeclaration,
functionName: string = 'functionDeclaration',
identifierName: string = 'identifierName',
identifierNode1: IIdentifierNode,
identifierNode2: IIdentifierNode,
identifierNode3: IIdentifierNode,
identifierNode1: ESTree.Identifier,
identifierNode2: ESTree.Identifier,
identifierNode3: ESTree.Identifier,
paramName: string = 'param1',
programNode: IProgramNode;
programNode: ESTree.Program;
before(() => {
identifierNode1 = NodeMocks.getIdentifierNode(paramName);
@@ -0,0 +1,21 @@
import * as chai 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', () => {
const blockScopeBodyLength1: number = 10000;
const blockScopeBodyLength2: number = 1000;
const blockScopeBodyLength3: number = 25;
const blockScopeBodyLength4: number = 5;
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength1), 44);
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength2), 26);
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength3), 24);
assert.equal(StackTraceAnalyzer.getLimitIndex(blockScopeBodyLength4), 4);
});
});
});