mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
performance boost
This commit is contained in:
Vendored
+332
-334
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
|
||||
|
||||
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
|
||||
import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
|
||||
import { IOptions } from '../../../interfaces/options/IOptions';
|
||||
|
||||
import { CustomNodes } from '../../../enums/container/CustomNodes';
|
||||
import { CustomNodeGroups } from '../../../enums/container/CustomNodeGroups';
|
||||
@@ -105,7 +106,25 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
|
||||
// customNode factory
|
||||
bind<ICustomNode>(ServiceIdentifiers['Factory<ICustomNode>'])
|
||||
.toFactory<ICustomNode>((context: interfaces.Context) => {
|
||||
let cachedOptions: IOptions;
|
||||
|
||||
return (customNodeName: CustomNodes) => {
|
||||
if (!cachedOptions) {
|
||||
cachedOptions = context.container.get<IOptions>(ServiceIdentifiers.IOptions);
|
||||
}
|
||||
|
||||
// we should avoid automatic resolve for custom nodes which will resolve during traverse over AST tree
|
||||
switch (customNodeName) {
|
||||
case CustomNodes.BinaryExpressionFunctionNode:
|
||||
return new BinaryExpressionFunctionNode(cachedOptions);
|
||||
|
||||
case CustomNodes.ControlFlowStorageCallNode:
|
||||
return new ControlFlowStorageCallNode(cachedOptions);
|
||||
|
||||
case CustomNodes.ControlFlowStorageNode:
|
||||
return new ControlFlowStorageNode(cachedOptions);
|
||||
}
|
||||
|
||||
return context.container.getNamed<ICustomNode>(
|
||||
ServiceIdentifiers.ICustomNode,
|
||||
customNodeName
|
||||
|
||||
@@ -26,7 +26,7 @@ export const storagesModule: interfaces.ContainerModule = new ContainerModule((b
|
||||
bind<IStorage<ICustomNode>>(ServiceIdentifiers['Factory<IStorage<ICustomNode>>'])
|
||||
.toFactory<IStorage<ICustomNode>>((context: interfaces.Context) => {
|
||||
return () => {
|
||||
return context.container.get<IStorage<ICustomNode>>(ServiceIdentifiers['IStorage<ICustomNode>']);
|
||||
return new ControlFlowStorage();
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -108,7 +108,7 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
|
||||
const stringArrayStorageId: string = this.stringArrayStorage.getStorageId();
|
||||
|
||||
const stringArrayName: string = `_${Utils.hexadecimalPrefix}${stringArrayStorageId}`;
|
||||
const stringArrayCallsWrapperName: string = `_${Utils.hexadecimalPrefix}${Utils.stringRotate(stringArrayStorageId, 2)}`;
|
||||
const stringArrayCallsWrapperName: string = `_${Utils.hexadecimalPrefix}${Utils.stringRotate(stringArrayStorageId, 1)}`;
|
||||
|
||||
let stringArrayRotateValue: number;
|
||||
|
||||
|
||||
+8
-10
@@ -129,9 +129,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
|
||||
const controlFlowStorage: IStorage <ICustomNode> = this.controlFlowStorageFactory();
|
||||
const hostNode: TNodeWithBlockStatement = FunctionControlFlowTransformer.getHostNode(functionNode);
|
||||
|
||||
if (!this.controlFlowData.has(hostNode)) {
|
||||
this.controlFlowData.set(hostNode, controlFlowStorage);
|
||||
} else {
|
||||
if (this.controlFlowData.has(hostNode)) {
|
||||
if (this.hostNodesWithControlFlowNode.indexOf(hostNode) !== -1) {
|
||||
hostNode.body.shift();
|
||||
}
|
||||
@@ -139,23 +137,23 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
|
||||
const hostControlFlowStorage: IStorage<ICustomNode> = <IStorage<ICustomNode>>this.controlFlowData.get(hostNode);
|
||||
|
||||
controlFlowStorage.mergeWith(hostControlFlowStorage, true);
|
||||
|
||||
this.controlFlowData.set(hostNode, controlFlowStorage);
|
||||
}
|
||||
|
||||
this.controlFlowData.set(hostNode, controlFlowStorage);
|
||||
|
||||
estraverse.replace(functionNode.body, {
|
||||
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
|
||||
if (!FunctionControlFlowTransformer.controlFlowReplacersMap.has(node.type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RandomGeneratorUtils.getRandomFloat(0, 1) > this.options.controlFlowFlatteningThreshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
const controlFlowReplacerName: NodeControlFlowReplacers | undefined = FunctionControlFlowTransformer
|
||||
const controlFlowReplacerName: NodeControlFlowReplacers = <NodeControlFlowReplacers>FunctionControlFlowTransformer
|
||||
.controlFlowReplacersMap.get(node.type);
|
||||
|
||||
if (controlFlowReplacerName === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
...this.controlFlowReplacerFactory(controlFlowReplacerName)
|
||||
.replace(node, parentNode, controlFlowStorage),
|
||||
|
||||
@@ -2,7 +2,6 @@ import { injectable, inject } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
|
||||
import * as escodegen from 'escodegen';
|
||||
import * as estraverse from 'estraverse';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
@@ -38,24 +37,18 @@ export class MemberExpressionObfuscator extends AbstractNodeTransformer {
|
||||
* @param memberExpressionNode
|
||||
*/
|
||||
public transformNode (memberExpressionNode: ESTree.MemberExpression): void {
|
||||
estraverse.traverse(memberExpressionNode.property, {
|
||||
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
|
||||
if (Node.isLiteralNode(node)) {
|
||||
this.obfuscateLiteralProperty(node);
|
||||
if (Node.isLiteralNode(memberExpressionNode.property)) {
|
||||
memberExpressionNode.property = this.obfuscateLiteralProperty(memberExpressionNode.property);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Node.isIdentifierNode(node)) {
|
||||
if (memberExpressionNode.computed) {
|
||||
return;
|
||||
}
|
||||
|
||||
memberExpressionNode.computed = true;
|
||||
this.obfuscateIdentifierProperty(node);
|
||||
}
|
||||
if (Node.isIdentifierNode(memberExpressionNode.property)) {
|
||||
if (memberExpressionNode.computed) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
memberExpressionNode.computed = true;
|
||||
memberExpressionNode.property = this.obfuscateIdentifierProperty(memberExpressionNode.property);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,22 +62,18 @@ export class MemberExpressionObfuscator extends AbstractNodeTransformer {
|
||||
* object[identifier] = 1;
|
||||
*
|
||||
* @param node
|
||||
* @returns {ESTree.Literal}
|
||||
*/
|
||||
private obfuscateIdentifierProperty (node: ESTree.Identifier): void {
|
||||
const nodeValue: string = node.name;
|
||||
const literalNode: ESTree.Literal = {
|
||||
raw: `'${nodeValue}'`,
|
||||
'x-verbatim-property': {
|
||||
content: this.stringLiteralReplacer.replace(nodeValue),
|
||||
precedence: escodegen.Precedence.Primary
|
||||
},
|
||||
private obfuscateIdentifierProperty (node: ESTree.Identifier): ESTree.Literal {
|
||||
return {
|
||||
type: NodeType.Literal,
|
||||
value: nodeValue
|
||||
value: node.name,
|
||||
raw: `'${node.name}'`,
|
||||
'x-verbatim-property': {
|
||||
content: this.stringLiteralReplacer.replace(node.name),
|
||||
precedence: escodegen.Precedence.Primary
|
||||
}
|
||||
};
|
||||
|
||||
delete node.name;
|
||||
|
||||
Object.assign(node, literalNode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,13 +84,16 @@ export class MemberExpressionObfuscator extends AbstractNodeTransformer {
|
||||
* object[_0x23d45[25]] = 1;
|
||||
*
|
||||
* @param node
|
||||
* @returns {ESTree.Literal}
|
||||
*/
|
||||
private obfuscateLiteralProperty (node: ESTree.Literal): void {
|
||||
private obfuscateLiteralProperty (node: ESTree.Literal): ESTree.Literal {
|
||||
if (typeof node.value === 'string' && !node['x-verbatim-property']) {
|
||||
node['x-verbatim-property'] = {
|
||||
content : this.stringLiteralReplacer.replace(node.value),
|
||||
content: this.stringLiteralReplacer.replace(node.value),
|
||||
precedence: escodegen.Precedence.Primary
|
||||
};
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ export class StringLiteralReplacer extends AbstractReplacer {
|
||||
this.stringArrayStorage.set(null, value);
|
||||
}
|
||||
|
||||
const rotatedStringArrayStorageId: string = Utils.stringRotate(this.stringArrayStorage.getStorageId(), 2);
|
||||
const rotatedStringArrayStorageId: string = Utils.stringRotate(this.stringArrayStorage.getStorageId(), 1);
|
||||
const stringArrayStorageCallsWrapperName: string = `_${Utils.hexadecimalPrefix}${rotatedStringArrayStorageId}`;
|
||||
const hexadecimalIndex: string = `${Utils.hexadecimalPrefix}${Utils.decToHex(indexOfValue)}`;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ export abstract class MapStorage <T> implements IStorage <T> {
|
||||
* @returns {number}
|
||||
*/
|
||||
public getLength (): number {
|
||||
return Array.from(this.storage).length;
|
||||
return this.storage.size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+10
-2
@@ -98,7 +98,15 @@ export class Utils {
|
||||
* @returns {string}
|
||||
*/
|
||||
public static stringRotate (string: string, times: number): string {
|
||||
return Utils.arrayRotate(Array.from(string), times).join('');
|
||||
if (!string) {
|
||||
throw new ReferenceError(`Cannot rotate empty string.`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < times; i++) {
|
||||
string = string[string.length - 1] + string.substring(0, string.length - 1);
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +141,7 @@ export class Utils {
|
||||
prefix = '\\u';
|
||||
template = '0'.repeat(4);
|
||||
}
|
||||
|
||||
|
||||
return `${prefix}${(template + escape.charCodeAt(0).toString(radix)).slice(-template.length)}`;
|
||||
})}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user