Reorganized transformers structure and order

This commit is contained in:
sanex
2020-08-23 09:27:35 +03:00
parent 7fb26b3a66
commit 9c04ededc7
161 changed files with 1416 additions and 1678 deletions
@@ -0,0 +1,231 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeFactory } from '../../node/NodeFactory';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeLiteralUtils } from '../../node/NodeLiteralUtils';
import { NodeMetadata } from '../../node/NodeMetadata';
import { NodeUtils } from '../../node/NodeUtils';
import { NumberUtils } from '../../utils/NumberUtils';
@injectable()
export class StringArrayTransformer extends AbstractNodeTransformer {
/**
* @type {NodeTransformer[]}
*/
public readonly runAfter: NodeTransformer[] = [
NodeTransformer.MemberExpressionTransformer
];
/**
* @type {IEscapeSequenceEncoder}
*/
private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
/**
* @type {Map<string, ESTree.Node>}
*/
private readonly nodesCache: Map <string, ESTree.Node> = new Map();
/**
* @type {IStringArrayStorage}
*/
private readonly stringArrayStorage: IStringArrayStorage;
/**
* @type {IStringArrayStorageAnalyzer}
*/
private readonly stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer;
/**
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {IStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
*/
public constructor (
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
@inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
) {
super(randomGenerator, options);
this.stringArrayStorage = stringArrayStorage;
this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
this.escapeSequenceEncoder = escapeSequenceEncoder;
}
/**
* @param {string} hexadecimalIndex
* @returns {Literal}
*/
private static getHexadecimalLiteralNode (hexadecimalIndex: string): ESTree.Literal {
const hexadecimalLiteralNode: ESTree.Literal = NodeFactory.literalNode(hexadecimalIndex);
NodeMetadata.set(hexadecimalLiteralNode, { replacedLiteral: true });
return hexadecimalLiteralNode;
}
/**
* @param {string} literalValue
* @returns {Literal}
*/
private static getRc4KeyLiteralNode (literalValue: string): ESTree.Literal {
const rc4KeyLiteralNode: ESTree.Literal = NodeFactory.literalNode(literalValue);
NodeMetadata.set(rc4KeyLiteralNode, { replacedLiteral: true });
return rc4KeyLiteralNode;
}
/**
* @param {NodeTransformationStage} nodeTransformationStage
* @returns {IVisitor | null}
*/
public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
switch (nodeTransformationStage) {
case NodeTransformationStage.StringArray:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
if (NodeGuards.isProgramNode(node)) {
this.prepareNode(node);
}
if (parentNode && NodeGuards.isLiteralNode(node) && !NodeMetadata.isReplacedLiteral(node)) {
return this.transformNode(node, parentNode);
}
}
};
case NodeTransformationStage.Finalizing:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
if (parentNode && NodeGuards.isLiteralNode(node)) {
return this.encodeLiteralNodeToEscapeSequence(node, parentNode);
}
}
};
default:
return null;
}
}
/**
* @param {Program} programNode
*/
public prepareNode (programNode: ESTree.Program): void {
this.stringArrayStorageAnalyzer.analyze(programNode);
if (this.options.shuffleStringArray) {
this.stringArrayStorage.shuffleStorage();
}
if (this.options.rotateStringArray) {
this.stringArrayStorage.rotateStorage();
}
}
/**
* @param {Literal} literalNode
* @param {NodeGuards} parentNode
* @returns {NodeGuards}
*/
public transformNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): ESTree.Node {
if (typeof literalNode.value !== 'string' || NodeLiteralUtils.isProhibitedLiteralNode(literalNode, parentNode)) {
return literalNode;
}
const literalValue: ESTree.SimpleLiteral['value'] = literalNode.value;
const stringArrayStorageItemData: IStringArrayStorageItemData | undefined = this.stringArrayStorageAnalyzer
.getItemDataForLiteralNode(literalNode);
const cacheKey: string = `${literalValue}-${Boolean(stringArrayStorageItemData)}`;
const useCachedValue: boolean = this.nodesCache.has(cacheKey) && this.options.stringArrayEncoding !== StringArrayEncoding.Rc4;
if (useCachedValue) {
return <ESTree.Node>this.nodesCache.get(cacheKey);
}
const resultNode: ESTree.Node = stringArrayStorageItemData
? this.getStringArrayCallNode(stringArrayStorageItemData)
: this.getLiteralNode(literalValue);
this.nodesCache.set(cacheKey, resultNode);
NodeUtils.parentizeNode(resultNode, parentNode);
return resultNode;
}
/**
* @param {string} value
* @returns {Node}
*/
private getLiteralNode (value: string): ESTree.Node {
return NodeFactory.literalNode(value);
}
/**
* @param {IStringArrayStorageItemData} stringArrayStorageItemData
* @returns {Node}
*/
private getStringArrayCallNode (stringArrayStorageItemData: IStringArrayStorageItemData): ESTree.Node {
const { index, decodeKey } = stringArrayStorageItemData;
const hexadecimalIndex: string = NumberUtils.toHex(index);
const callExpressionArgs: (ESTree.Expression | ESTree.SpreadElement)[] = [
StringArrayTransformer.getHexadecimalLiteralNode(hexadecimalIndex)
];
if (decodeKey) {
callExpressionArgs.push(StringArrayTransformer.getRc4KeyLiteralNode(decodeKey));
}
const stringArrayIdentifierNode: ESTree.Identifier = NodeFactory.identifierNode(
this.stringArrayStorage.getStorageCallsWrapperName()
);
return NodeFactory.callExpressionNode(
stringArrayIdentifierNode,
callExpressionArgs
);
}
/**
* @param {Literal} literalNode
* @param {Node} parentNode
* @returns {Literal}
*/
private encodeLiteralNodeToEscapeSequence (
literalNode: ESTree.Literal,
parentNode: ESTree.Node
): ESTree.Literal {
if (typeof literalNode.value !== 'string') {
return literalNode;
}
return NodeFactory.literalNode(
this.escapeSequenceEncoder.encode(literalNode.value, this.options.unicodeEscapeSequence)
);
}
}