Syncing with master

This commit is contained in:
sanex3339
2018-02-17 20:19:07 +03:00
20 changed files with 744 additions and 10113 deletions
+27 -5
View File
@@ -7,18 +7,40 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
(function(){
var foo = 'foo'; var bar = 'bar'; var bark = foo + bar,; var baz = 'baz';
function foo () {
var a = 1;
inner1();
var b = 2;
function inner1 () {}
var c = 3;
}
function bar () {
var a = 1;
}
function baz () {
var a = 1;
}
function bark () {
var a = 1;
}
function hawk () {
var a = 1;
}
function eagle () {
var a = 1;
}
})();
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
identifiersPrefix: 'foo',
identifierNamesGenerator: 'mangled',
renameGlobals: true
stringArray: true,
stringArrayThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1
}
).getObfuscatedCode();
console.log(obfuscatedCode);
console.log(eval(obfuscatedCode));
})();
})();
@@ -24,7 +24,74 @@ describe('TemplateLiteralTransformer', () => {
});
});
describe('variant #1: simple template literal with expression only', () => {
describe('variant #2: multiline template literals', () => {
it('variant #1: should transform es6 multiline template literal to es5', () => {
const code: string = readFileAsString(__dirname + '/fixtures/multiline-template-literal.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
unicodeEscapeSequence: false
}
);
assert.match(obfuscationResult.getObfuscatedCode(), /^var *test *= *'foo\\x0abar';$/);
});
it('variant #2: should transform es6 multiline template literal inside return statement', () => {
const code: string = readFileAsString(__dirname + '/fixtures/multiline-template-literal-return-statement-1.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
unicodeEscapeSequence: false
}
);
assert.match(obfuscationResult.getObfuscatedCode(), /{ *return *'foo\\x0abar'; *}$/);
});
it('variant #3: should transform es6 multiline template literal inside return statement', () => {
const code: string = readFileAsString(__dirname + '/fixtures/multiline-template-literal-return-statement-2.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
unicodeEscapeSequence: false
}
);
assert.match(obfuscationResult.getObfuscatedCode(), /case *!!\[] *: *return *'foo\\x0abar'; *} *}$/);
});
it('variant #4: should transform es6 multiline template literal inside binary expression inside return statement', () => {
const code: string = readFileAsString(__dirname + '/fixtures/multiline-template-literal-binary-expression-return-statement-1.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
unicodeEscapeSequence: false
}
);
assert.match(obfuscationResult.getObfuscatedCode(), /{ *return *'foo\\x0abar' *\+ *0x1; *}$/);
});
it('variant #5: should transform es6 multiline template literal inside binary expression inside return statement', () => {
const code: string = readFileAsString(__dirname + '/fixtures/multiline-template-literal-binary-expression-return-statement-2.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
unicodeEscapeSequence: false
}
);
assert.match(obfuscationResult.getObfuscatedCode(), /case *!!\[] *: *return *'foo\\x0abar' *\+ *0x1; *} *}$/);
});
});
describe('variant #3: simple template literal with expression only', () => {
it('should transform es6 template literal to es5 and add empty literal node before expression node', () => {
const code: string = readFileAsString(__dirname + '/fixtures/expression-only.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
@@ -39,7 +106,7 @@ describe('TemplateLiteralTransformer', () => {
});
});
describe('variant #3: literal node inside expression', () => {
describe('variant #4: literal node inside expression', () => {
it('should transform es6 template literal to es5', () => {
const code: string = readFileAsString(__dirname + '/fixtures/literal-inside-expression.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
@@ -54,7 +121,7 @@ describe('TemplateLiteralTransformer', () => {
});
});
describe('variant #4: multiple expressions', () => {
describe('variant #5: multiple expressions', () => {
it('should transform es6 template literal to es5', () => {
const code: string = readFileAsString(__dirname + '/fixtures/multiple-expressions.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
@@ -0,0 +1,7 @@
function hi() {
switch (true) {
case true:
return `foo
bar`;
}
}
@@ -481,5 +481,115 @@ describe('DeadCodeInjectionTransformer', () => {
assert.notEqual(returnIdentifierName, variableDeclarationIdentifierName);
});
});
describe('variant #11 - block statements with empty body', () => {
const regExp: RegExp = new RegExp(
`function *${variableMatch} *\\(\\) *{ *} *` +
`${variableMatch} *\\(\\); *`,
'g'
);
const expectedMatchesLength: number = 5;
let matchesLength: number = 0;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/block-statement-empty-body.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1
}
);
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
const functionMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(regExp);
if (functionMatches) {
matchesLength = functionMatches.length;
}
});
it('shouldn\'t add dead code conditions to the block empty block statements', () => {
assert.isAtLeast(matchesLength, expectedMatchesLength);
});
});
describe('variant #12 - block statement with scope-hoisting', () => {
describe('variant #1: collecting of block statements', () => {
const regExp: RegExp = new RegExp(
`${variableMatch} *\\(\\); *` +
`var *${variableMatch} *= *0x2; *` +
`function *${variableMatch} *\\(\\) *{ *} *`,
'g'
);
const expectedMatchesLength: number = 5;
let matchesLength: number = 0;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/block-statement-with-scope-hoisting-1.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1
}
);
const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
const functionMatches: RegExpMatchArray = <RegExpMatchArray>obfuscatedCode.match(regExp);
if (functionMatches) {
matchesLength = functionMatches.length;
}
});
it('shouldn\'t collect block statements with scope-hoisting', () => {
assert.equal(matchesLength, expectedMatchesLength);
});
});
describe('variant #2: wrapping of block statements in dead code conditions', () => {
const regExp: RegExp = new RegExp(
`function *${variableMatch} *\\(\\) *{ *` +
`var *${variableMatch} *= *0x1; *` +
`${variableMatch} *\\(\\); *` +
`var *${variableMatch} *= *0x2; *` +
`function *${variableMatch} *\\(\\) *{ *} *` +
`var *${variableMatch} *= *0x3; *` +
`}`,
'g'
);
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/block-statement-with-scope-hoisting-2.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1
}
);
obfuscatedCode = obfuscationResult.getObfuscatedCode();
});
it('shouldn\'t wrap block statements in dead code conditions', () => {
assert.match(obfuscatedCode, regExp);
});
});
});
});
});
@@ -0,0 +1,22 @@
(function(){
function foo () {
function inner1 () {}
inner1();
}
function bar () {
function inner2 () {}
inner2();
}
function baz () {
function inner3 () {}
inner3();
}
function bark () {
function inner4 () {}
inner4();
}
function hawk () {
function inner5 () {}
inner5();
}
})();
@@ -0,0 +1,37 @@
(function(){
function foo () {
var a = 1;
inner1();
var b = 2;
function inner1 () {}
var c = 3;
}
function bar () {
var a = 1;
inner2();
var b = 2;
function inner2 () {}
var c = 3;
}
function baz () {
var a = 1;
inner3();
var b = 2;
function inner3 () {}
var c = 3;
}
function bark () {
var a = 1;
inner4();
var b = 2;
function inner4 () {}
var c = 3;
}
function hawk () {
var a = 1;
inner5();
var b = 2;
function inner5 () {}
var c = 3;
}
})();
@@ -0,0 +1,24 @@
(function(){
function foo () {
var a = 1;
inner1();
var b = 2;
function inner1 () {}
var c = 3;
}
function bar () {
var a = 1;
}
function baz () {
var a = 1;
}
function bark () {
var a = 1;
}
function hawk () {
var a = 1;
}
function eagle () {
var a = 1;
}
})();
@@ -294,6 +294,176 @@ describe('NodeUtils', () => {
});
});
describe('getNextSiblingStatementNode (node: ESTree.Statement): TStatement | null', () => {
describe('variant #1: block statement node as scope node', () => {
let statementNode1: ESTree.Statement,
statementNode2: ESTree.Statement,
statementNode3: ESTree.Statement;
before(() => {
statementNode1 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('a')
);
statementNode2 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('b')
);
statementNode3 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('c')
);
const blockStatementNode: ESTree.BlockStatement = Nodes.getBlockStatementNode([
statementNode1,
statementNode2,
statementNode3
]);
statementNode1.parentNode = blockStatementNode;
statementNode2.parentNode = blockStatementNode;
statementNode3.parentNode = blockStatementNode;
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getNextSiblingStatementNode(statementNode1), statementNode2);
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getNextSiblingStatementNode(statementNode2), statementNode3);
});
it('should return `null` if given statement node is last node in the scope', () => {
assert.deepEqual(NodeUtils.getNextSiblingStatementNode(statementNode3), null);
});
});
describe('variant #2: switch case node as scope node', () => {
let statementNode1: ESTree.Statement,
statementNode2: ESTree.Statement,
statementNode3: ESTree.Statement;
before(() => {
statementNode1 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('a')
);
statementNode2 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('b')
);
statementNode3 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('c')
);
const switchCaseNode: ESTree.SwitchCase = Nodes.getSwitchCaseNode(
Nodes.getLiteralNode(true),
[
statementNode1,
statementNode2,
statementNode3
]
);
statementNode1.parentNode = switchCaseNode;
statementNode2.parentNode = switchCaseNode;
statementNode3.parentNode = switchCaseNode;
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getNextSiblingStatementNode(statementNode1), statementNode2);
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getNextSiblingStatementNode(statementNode2), statementNode3);
});
it('should return `null` if given statement node is last node in the scope', () => {
assert.deepEqual(NodeUtils.getNextSiblingStatementNode(statementNode3), null);
});
});
});
describe('getPreviousSiblingStatementNode (node: ESTree.Statement): TStatement | null', () => {
describe('variant #1: block statement node as scope node', () => {
let statementNode1: ESTree.Statement,
statementNode2: ESTree.Statement,
statementNode3: ESTree.Statement;
before(() => {
statementNode1 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('a')
);
statementNode2 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('b')
);
statementNode3 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('c')
);
const blockStatementNode: ESTree.BlockStatement = Nodes.getBlockStatementNode([
statementNode1,
statementNode2,
statementNode3
]);
statementNode1.parentNode = blockStatementNode;
statementNode2.parentNode = blockStatementNode;
statementNode3.parentNode = blockStatementNode;
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getPreviousSiblingStatementNode(statementNode1), null);
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getPreviousSiblingStatementNode(statementNode2), statementNode1);
});
it('should return `null` if given statement node is last node in the scope', () => {
assert.deepEqual(NodeUtils.getPreviousSiblingStatementNode(statementNode3), statementNode2);
});
});
describe('variant #2: switch case node as scope node', () => {
let statementNode1: ESTree.Statement,
statementNode2: ESTree.Statement,
statementNode3: ESTree.Statement;
before(() => {
statementNode1 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('a')
);
statementNode2 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('b')
);
statementNode3 = Nodes.getExpressionStatementNode(
Nodes.getIdentifierNode('c')
);
const switchCaseNode: ESTree.SwitchCase = Nodes.getSwitchCaseNode(
Nodes.getLiteralNode(true),
[
statementNode1,
statementNode2,
statementNode3
]
);
statementNode1.parentNode = switchCaseNode;
statementNode2.parentNode = switchCaseNode;
statementNode3.parentNode = switchCaseNode;
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getPreviousSiblingStatementNode(statementNode1), null);
});
it('should return next sibling statement node', () => {
assert.deepEqual(NodeUtils.getPreviousSiblingStatementNode(statementNode2), statementNode1);
});
it('should return `null` if given statement node is last node in the scope', () => {
assert.deepEqual(NodeUtils.getPreviousSiblingStatementNode(statementNode3), statementNode2);
});
});
});
describe('getScopeOfNode (node: ESTree.Node): TNodeWithScope | null', () => {
let functionDeclarationBlockStatementNode: ESTree.BlockStatement,
ifStatementBlockStatementNode1: ESTree.BlockStatement,