mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Syncing with master
This commit is contained in:
+27
-5
@@ -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));
|
||||
})();
|
||||
})();
|
||||
+70
-3
@@ -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(
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function foo() {
|
||||
return `foo
|
||||
bar` + 1;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
function hi() {
|
||||
switch (true) {
|
||||
case true:
|
||||
return `foo
|
||||
bar` + 1;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function foo() {
|
||||
return `foo
|
||||
bar`;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
function hi() {
|
||||
switch (true) {
|
||||
case true:
|
||||
return `foo
|
||||
bar`;
|
||||
}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
var test = `foo
|
||||
bar`;
|
||||
+110
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+22
@@ -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();
|
||||
}
|
||||
})();
|
||||
+37
@@ -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;
|
||||
}
|
||||
})();
|
||||
+24
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user