mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
154 lines
4.4 KiB
TypeScript
154 lines
4.4 KiB
TypeScript
import * as escodegen from '@javascript-obfuscator/escodegen';
|
|
import * as estraverse from 'estraverse';
|
|
import * as ESTree from 'estree';
|
|
|
|
import { ecmaVersion } from '../constants/EcmaVersion';
|
|
|
|
import { ASTParserFacade } from '../ASTParserFacade';
|
|
import { NodeGuards } from './NodeGuards';
|
|
import { NodeMetadata } from './NodeMetadata';
|
|
|
|
export class NodeUtils {
|
|
/**
|
|
* @param {ESTree.Literal} literalNode
|
|
* @returns {ESTree.Literal}
|
|
*/
|
|
public static addXVerbatimPropertyTo (literalNode: ESTree.Literal): ESTree.Literal {
|
|
literalNode['x-verbatim-property'] = {
|
|
content: literalNode.raw,
|
|
precedence: escodegen.Precedence.Primary
|
|
};
|
|
|
|
return literalNode;
|
|
}
|
|
|
|
/**
|
|
* @param {T} astTree
|
|
* @returns {T}
|
|
*/
|
|
public static clone <T extends ESTree.Node = ESTree.Node> (astTree: T): T {
|
|
return NodeUtils.parentizeAst(NodeUtils.cloneRecursive(astTree));
|
|
}
|
|
|
|
/**
|
|
* @param {string} code
|
|
* @returns {ESTree.Statement[]}
|
|
*/
|
|
public static convertCodeToStructure (code: string): ESTree.Statement[] {
|
|
const structure: ESTree.Program = ASTParserFacade.parse(
|
|
code,
|
|
{
|
|
ecmaVersion,
|
|
sourceType: 'script'
|
|
}
|
|
);
|
|
|
|
estraverse.replace(structure, {
|
|
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node => {
|
|
NodeUtils.parentizeNode(node, parentNode);
|
|
|
|
if (NodeGuards.isLiteralNode(node)) {
|
|
NodeUtils.addXVerbatimPropertyTo(node);
|
|
}
|
|
|
|
NodeMetadata.set(node, { ignoredNode: false });
|
|
|
|
return node;
|
|
}
|
|
});
|
|
|
|
return <ESTree.Statement[]>structure.body;
|
|
}
|
|
|
|
/**
|
|
* @param {NodeGuards[]} structure
|
|
* @returns {string}
|
|
*/
|
|
public static convertStructureToCode (structure: ESTree.Node[]): string {
|
|
return structure.reduce((code: string, node: ESTree.Node) => {
|
|
return code + escodegen.generate(node, {
|
|
sourceMapWithCode: true
|
|
}).code;
|
|
}, '');
|
|
}
|
|
|
|
/**
|
|
* @param {UnaryExpression} unaryExpressionNode
|
|
* @returns {NodeGuards}
|
|
*/
|
|
public static getUnaryExpressionArgumentNode (unaryExpressionNode: ESTree.UnaryExpression): ESTree.Node {
|
|
if (NodeGuards.isUnaryExpressionNode(unaryExpressionNode.argument)) {
|
|
return NodeUtils.getUnaryExpressionArgumentNode(unaryExpressionNode.argument);
|
|
}
|
|
|
|
return unaryExpressionNode.argument;
|
|
}
|
|
|
|
/**
|
|
* @param {T} astTree
|
|
* @returns {T}
|
|
*/
|
|
public static parentizeAst <T extends ESTree.Node = ESTree.Node> (astTree: T): T {
|
|
const parentNode: ESTree.Node | null = astTree.parentNode ?? null;
|
|
|
|
estraverse.replace(astTree, {
|
|
enter: NodeUtils.parentizeNode
|
|
});
|
|
|
|
if (parentNode) {
|
|
astTree.parentNode = parentNode;
|
|
}
|
|
|
|
return astTree;
|
|
}
|
|
|
|
/**
|
|
* @param {T} node
|
|
* @param {Node} parentNode
|
|
* @returns {T}
|
|
*/
|
|
public static parentizeNode <T extends ESTree.Node = ESTree.Node> (node: T, parentNode: ESTree.Node | null): T {
|
|
node.parentNode = parentNode ?? node;
|
|
|
|
return node;
|
|
}
|
|
|
|
/**
|
|
* @param {T} node
|
|
* @returns {T}
|
|
*/
|
|
private static cloneRecursive <T> (node: T): T {
|
|
if (node === null) {
|
|
return node;
|
|
}
|
|
|
|
const copy: Partial<T> = {};
|
|
const nodeKeys: (keyof T)[] = <(keyof T)[]>Object.keys(node);
|
|
|
|
nodeKeys
|
|
.forEach((property: keyof T) => {
|
|
if (property === 'parentNode') {
|
|
return;
|
|
}
|
|
|
|
const value: T[keyof T] | T[keyof T][] | null = node[property] ?? null;
|
|
|
|
let clonedValue: T[keyof T] | T[keyof T][] | null;
|
|
|
|
if (value === null || value instanceof RegExp) {
|
|
clonedValue = value;
|
|
} else if (value instanceof Array) {
|
|
clonedValue = value.map(NodeUtils.cloneRecursive);
|
|
} else if (typeof value === 'object') {
|
|
clonedValue = NodeUtils.cloneRecursive(value);
|
|
} else {
|
|
clonedValue = value;
|
|
}
|
|
|
|
copy[property] = <T[keyof T]>clonedValue;
|
|
});
|
|
|
|
return <T>copy;
|
|
}
|
|
}
|