mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
ExpressionStatementsMergeTransformer + optimized AbstractStatementSimplifyTransformer logic
This commit is contained in:
Vendored
+6
-6
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -68,6 +68,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
|
||||
NodeTransformer.CustomCodeHelpersTransformer,
|
||||
NodeTransformer.DeadCodeInjectionTransformer,
|
||||
NodeTransformer.EvalCallExpressionTransformer,
|
||||
NodeTransformer.ExpressionStatementsMergeTransformer,
|
||||
NodeTransformer.FunctionControlFlowTransformer,
|
||||
NodeTransformer.IfStatementSimplifyTransformer,
|
||||
NodeTransformer.LabeledStatementTransformer,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { INodeTransformer } from '../../../interfaces/node-transformers/INodeTra
|
||||
import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
|
||||
|
||||
import { BlockStatementSimplifyTransformer } from '../../../node-transformers/simplifying-transformers/BlockStatementSimplifyTransformer';
|
||||
import { ExpressionStatementsMergeTransformer } from '../../../node-transformers/simplifying-transformers/ExpressionStatementsMergeTransformer';
|
||||
import { IfStatementSimplifyTransformer } from '../../../node-transformers/simplifying-transformers/IfStatementSimplifyTransformer';
|
||||
import { VariableDeclarationsMergeTransformer } from '../../../node-transformers/simplifying-transformers/VariableDeclarationsMergeTransformer';
|
||||
|
||||
@@ -15,6 +16,10 @@ export const simplifyingTransformersModule: interfaces.ContainerModule = new Con
|
||||
.to(BlockStatementSimplifyTransformer)
|
||||
.whenTargetNamed(NodeTransformer.BlockStatementSimplifyTransformer);
|
||||
|
||||
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
|
||||
.to(ExpressionStatementsMergeTransformer)
|
||||
.whenTargetNamed(NodeTransformer.ExpressionStatementsMergeTransformer);
|
||||
|
||||
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
|
||||
.to(IfStatementSimplifyTransformer)
|
||||
.whenTargetNamed(NodeTransformer.IfStatementSimplifyTransformer);
|
||||
|
||||
@@ -5,6 +5,7 @@ export enum NodeTransformer {
|
||||
CustomCodeHelpersTransformer = 'CustomCodeHelpersTransformer',
|
||||
DeadCodeInjectionTransformer = 'DeadCodeInjectionTransformer',
|
||||
EvalCallExpressionTransformer = 'EvalCallExpressionTransformer',
|
||||
ExpressionStatementsMergeTransformer = 'ExpressionStatementsMergeTransformer',
|
||||
FunctionControlFlowTransformer = 'FunctionControlFlowTransformer',
|
||||
IfStatementSimplifyTransformer = 'IfStatementSimplifyTransformer',
|
||||
LabeledStatementTransformer = 'LabeledStatementTransformer',
|
||||
|
||||
+13
-10
@@ -23,6 +23,7 @@ export abstract class AbstractStatementSimplifyTransformer extends AbstractNodeT
|
||||
* @type {NodeTransformer[]}
|
||||
*/
|
||||
public readonly runAfter: NodeTransformer[] = [
|
||||
NodeTransformer.ExpressionStatementsMergeTransformer,
|
||||
NodeTransformer.VariableDeclarationsMergeTransformer
|
||||
];
|
||||
|
||||
@@ -110,17 +111,19 @@ export abstract class AbstractStatementSimplifyTransformer extends AbstractNodeT
|
||||
const unwrappedExpressions: ESTree.Expression[] = [];
|
||||
|
||||
let hasReturnStatement: boolean = false;
|
||||
let startIndex: number | null = 0;
|
||||
let startIndex: number | null = null;
|
||||
|
||||
for (let i = 0; i < statementNodeBodyLength; i++) {
|
||||
for (let i = statementNodeBodyLength - 1; i >= 0; i--) {
|
||||
const statementBodyStatementNode: ESTree.Statement = statementNode.body[i];
|
||||
|
||||
if (startIndex === null) {
|
||||
startIndex = i;
|
||||
}
|
||||
|
||||
if (NodeGuards.isExpressionStatementNode(statementBodyStatementNode)) {
|
||||
unwrappedExpressions.push(statementBodyStatementNode.expression);
|
||||
if (NodeGuards.isSequenceExpressionNode(statementBodyStatementNode.expression)) {
|
||||
unwrappedExpressions.unshift(...statementBodyStatementNode.expression.expressions);
|
||||
} else {
|
||||
unwrappedExpressions.unshift(statementBodyStatementNode.expression);
|
||||
}
|
||||
|
||||
startIndex = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -128,13 +131,13 @@ export abstract class AbstractStatementSimplifyTransformer extends AbstractNodeT
|
||||
NodeGuards.isReturnStatementNode(statementBodyStatementNode)
|
||||
&& statementBodyStatementNode.argument
|
||||
) {
|
||||
unwrappedExpressions.push(statementBodyStatementNode.argument);
|
||||
unwrappedExpressions.unshift(statementBodyStatementNode.argument);
|
||||
hasReturnStatement = true;
|
||||
startIndex = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
startIndex = null;
|
||||
unwrappedExpressions.length = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
import { inject, injectable, } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
|
||||
import * as estraverse from 'estraverse';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TStatement } from '../../types/node/TStatement';
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
||||
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
|
||||
|
||||
import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
|
||||
|
||||
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
|
||||
import { NodeFactory } from '../../node/NodeFactory';
|
||||
import { NodeGuards } from '../../node/NodeGuards';
|
||||
import { NodeStatementUtils } from '../../node/NodeStatementUtils';
|
||||
import { NodeUtils } from '../../node/NodeUtils';
|
||||
|
||||
/**
|
||||
* replaces:
|
||||
* console.log(1);
|
||||
* console.log(2);
|
||||
*
|
||||
* on:
|
||||
* (console.log(1), console.log(2));
|
||||
*/
|
||||
@injectable()
|
||||
export class ExpressionStatementsMergeTransformer extends AbstractNodeTransformer {
|
||||
/**
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @param {IOptions} options
|
||||
*/
|
||||
public constructor (
|
||||
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions
|
||||
) {
|
||||
super(randomGenerator, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NodeTransformationStage} nodeTransformationStage
|
||||
* @returns {IVisitor | null}
|
||||
*/
|
||||
public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
|
||||
switch (nodeTransformationStage) {
|
||||
case NodeTransformationStage.Simplifying:
|
||||
return {
|
||||
leave: (
|
||||
node: ESTree.Node,
|
||||
parentNode: ESTree.Node | null
|
||||
): ESTree.Node | estraverse.VisitorOption | undefined => {
|
||||
if (parentNode && NodeGuards.isExpressionStatementNode(node)) {
|
||||
return this.transformNode(node, parentNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ESTree.ExpressionStatement} expressionStatementNode
|
||||
* @param {ESTree.Node} parentNode
|
||||
* @returns {ESTree.ExpressionStatement | estraverse.VisitorOption}
|
||||
*/
|
||||
public transformNode (
|
||||
expressionStatementNode: ESTree.ExpressionStatement,
|
||||
parentNode: ESTree.Node
|
||||
): ESTree.ExpressionStatement | estraverse.VisitorOption {
|
||||
if (!NodeGuards.isNodeWithStatements(parentNode)) {
|
||||
return expressionStatementNode;
|
||||
}
|
||||
|
||||
const prevStatement: TStatement | null = NodeStatementUtils.getPreviousSiblingStatement(expressionStatementNode);
|
||||
|
||||
if (!prevStatement || !NodeGuards.isExpressionStatementNode(prevStatement)) {
|
||||
return expressionStatementNode;
|
||||
}
|
||||
|
||||
if (NodeGuards.isSequenceExpressionNode(prevStatement.expression)) {
|
||||
prevStatement.expression.expressions.push(expressionStatementNode.expression);
|
||||
} else {
|
||||
prevStatement.expression = NodeFactory.sequenceExpressionNode([
|
||||
prevStatement.expression,
|
||||
expressionStatementNode.expression
|
||||
]);
|
||||
}
|
||||
|
||||
NodeUtils.parentizeAst(prevStatement);
|
||||
|
||||
return estraverse.VisitorOption.Remove;
|
||||
}
|
||||
}
|
||||
+5
-8
@@ -7,14 +7,11 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
var foo = function () {};
|
||||
var bar = function () {
|
||||
var baz = function () {};
|
||||
var bark = function () {
|
||||
var hawk = 1;
|
||||
var dog = 2;
|
||||
};
|
||||
};
|
||||
function foo () {
|
||||
console.log(7);
|
||||
|
||||
return 9;
|
||||
}
|
||||
`,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
|
||||
|
||||
import { readFileAsString } from '../../../../helpers/readFileAsString';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
|
||||
|
||||
describe('ExpressionStatementsMergeTransformer', () => {
|
||||
describe('Variant #1: simple', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'function foo *\\(\\) *{ *' +
|
||||
'bar\\(\\), *' +
|
||||
'baz\\(\\), *' +
|
||||
'bark\\(\\); *' +
|
||||
'}'
|
||||
);
|
||||
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/simple.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should merge expression statements', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: complex', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'function foo *\\(\\) *{ *' +
|
||||
'console\\[\'log\']\\(0x1\\), *' +
|
||||
'console\\[\'log\']\\(0x2\\); *' +
|
||||
'function _0x([a-f0-9]){4,6} *\\(\\) *{ *} *' +
|
||||
'console\\[\'log\']\\(0x3\\), *' +
|
||||
'console\\[\'log\']\\(0x4\\), *' +
|
||||
'console\\[\'log\']\\(0x5\\); *' +
|
||||
'const _0x([a-f0-9]){4,6} *= *0x6; *' +
|
||||
'console\\[\'log\']\\(0x7\\); *' +
|
||||
'}'
|
||||
);
|
||||
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/complex.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should merge expression statements', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
});
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
function foo () {
|
||||
console.log(1);
|
||||
console.log(2);
|
||||
|
||||
function bar () {}
|
||||
|
||||
console.log(3);
|
||||
console.log(4);
|
||||
console.log(5);
|
||||
|
||||
const baz = 6;
|
||||
|
||||
console.log(7);
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
function foo () {
|
||||
bar();
|
||||
baz();
|
||||
bark();
|
||||
}
|
||||
@@ -95,6 +95,8 @@ import './functional-tests/node-transformers/converting-transformers/split-strin
|
||||
import './functional-tests/node-transformers/converting-transformers/template-literal-transformer/TemplateLiteralTransformer.spec';
|
||||
import './functional-tests/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.spec';
|
||||
import './functional-tests/node-transformers/initializing-transformers/comments-transformer/CommentsTransformer.spec';
|
||||
import './functional-tests/node-transformers/simplifying-transformers/block-statement-simplify-transformer/BlockStatementSimplifyTransformer.spec';
|
||||
import './functional-tests/node-transformers/simplifying-transformers/expression-statements-merge-transformer/ExpressionStatementsMergeTransformer.spec';
|
||||
import './functional-tests/node-transformers/simplifying-transformers/if-statement-simplify-transformer/IfStatementSimplifyTransformer.spec';
|
||||
import './functional-tests/node-transformers/simplifying-transformers/variable-declarations-merge-transformer/VariableDeclarationsMergeTransformer.spec';
|
||||
import './functional-tests/node-transformers/obfuscating-transformers/labeled-statement-transformer/LabeledStatementTransformer.spec';
|
||||
|
||||
Reference in New Issue
Block a user