String array improvement: fixed bugs

This commit is contained in:
sanex
2020-12-28 21:39:54 +03:00
parent cec4b3525a
commit 3b8af4b29a
20 changed files with 224 additions and 115 deletions
@@ -17,7 +17,7 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
/**
* @type {number}
*/
private static readonly additionalParts: number = 3;
public static readonly defaultAdditionalPartsCount: number = 3;
/**
* @type {Map<number, number[]>}
@@ -40,9 +40,13 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
/**
* @param {number} number
* @param {number} additionalPartsCount
* @returns {TNumberNumericalExpressionData}
*/
public analyze (number: number): TNumberNumericalExpressionData {
public analyze (
number: number,
additionalPartsCount: number
): TNumberNumericalExpressionData {
if (isNaN(number)) {
throw new Error('Given value is NaN');
}
@@ -51,16 +55,17 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
return [number];
}
const additionParts: number[] = this.generateAdditionParts(number);
const additionParts: number[] = this.generateAdditionParts(number, additionalPartsCount);
return additionParts.map((addition: number) => this.mixWithMultiplyParts(addition));
}
/**
* @param {number} number
* @param {number} additionalPartsCount
* @returns {number[]}
*/
private generateAdditionParts (number: number): number[] {
private generateAdditionParts (number: number, additionalPartsCount: number): number[] {
const additionParts = [];
const upperNumberLimit: number = Math.min(Math.abs(number * 2), Number.MAX_SAFE_INTEGER);
@@ -70,8 +75,8 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
let temporarySum = 0;
for (let i = 0; i < NumberNumericalExpressionAnalyzer.additionalParts; i++) {
if (i < NumberNumericalExpressionAnalyzer.additionalParts - 1) {
for (let i = 0; i < additionalPartsCount; i++) {
if (i < additionalPartsCount - 1) {
// trailing parts
let addition: number = this.randomGenerator.getRandomInteger(from, to);
@@ -86,19 +86,11 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
});
}
/**
* @param {Literal} literalNode
* @returns {IStringArrayStorageItemData | undefined}
*/
public getItemDataForLiteralNode (literalNode: ESTree.Literal): IStringArrayStorageItemData | undefined {
return this.stringArrayStorageData.get(literalNode);
}
/**
* @param {Literal} literalNode
* @param {Node} parentNode
*/
private analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
public analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
if (!NodeLiteralUtils.isStringLiteralNode(literalNode)) {
return;
}
@@ -111,12 +103,27 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
return;
}
this.addItemDataForLiteralNode(literalNode);
}
/**
* @param {(SimpleLiteral & {value: string}) | (RegExpLiteral & {value: string})} literalNode
*/
public addItemDataForLiteralNode (literalNode: ESTree.Literal & {value: string}): void {
this.stringArrayStorageData.set(
literalNode,
this.stringArrayStorage.getOrThrow(literalNode.value)
);
}
/**
* @param {Literal} literalNode
* @returns {IStringArrayStorageItemData | undefined}
*/
public getItemDataForLiteralNode (literalNode: ESTree.Literal): IStringArrayStorageItemData | undefined {
return this.stringArrayStorageData.get(literalNode);
}
/**
* @param {(SimpleLiteral & {value: string})} literalNode
* @returns {boolean}
@@ -33,14 +33,15 @@ export function StringArrayBase64DecodeTemplate (
{stringArrayCallsWrapperName}.${initializedIdentifier} = true;
}
const ignoreCache = {stringArrayName}[-1];
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
const firstValue = {stringArrayName}[0];
const cacheKey = index + firstValue;
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey];
if (ignoreCache || cachedValue === undefined) {
if (cachedValue === undefined) {
{selfDefendingCode}
value = {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier}(value);
{stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
{stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey] = value;
} else {
value = cachedValue;
}
@@ -26,10 +26,11 @@ export function StringArrayRC4DecodeTemplate (
{stringArrayCallsWrapperName}.${initializedIdentifier} = true;
}
const ignoreCache = {stringArrayName}[-1];
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
const firstValue = {stringArrayName}[0];
const cacheKey = index + firstValue;
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey];
if (ignoreCache || cachedValue === undefined) {
if (cachedValue === undefined) {
if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {
{selfDefendingCode}
@@ -37,7 +38,7 @@ export function StringArrayRC4DecodeTemplate (
}
value = {stringArrayCallsWrapperName}.${rc4Identifier}(value, key);
{stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
{stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey] = value;
} else {
value = cachedValue;
}
@@ -4,14 +4,11 @@
export function StringArrayRotateFunctionTemplate (): string {
return `
(function (array, comparisonValue) {
array[-1] = true;
while (true) {
try {
const expression = {comparisonExpressionCode};
if (expression === comparisonValue) {
array[-1] = false;
break;
} else {
array['push'](array['shift']());
@@ -2,10 +2,14 @@ import { TNumberNumericalExpressionData } from '../../../types/analyzers/number-
import { IAnalyzer } from '../IAnalyzer';
export interface INumberNumericalExpressionAnalyzer extends IAnalyzer<[number], TNumberNumericalExpressionData> {
export interface INumberNumericalExpressionAnalyzer extends IAnalyzer<[number, number], TNumberNumericalExpressionData> {
/**
* @param {number} number
* @param {number} additionalPartsCount
* @returns {TNumberNumericalExpressionData}
*/
analyze (number: number): TNumberNumericalExpressionData;
analyze (
number: number,
additionalPartsCount: number
): TNumberNumericalExpressionData;
}
@@ -9,6 +9,17 @@ export interface IStringArrayStorageAnalyzer extends IAnalyzer<[ESTree.Program],
*/
analyze (astTree: ESTree.Program): void;
/**
* @param {Literal} literalNode
* @param {Node} parentNode
*/
analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void;
/**
* @param {(SimpleLiteral & {value: string}) | (RegExpLiteral & {value: string})} literalNode
*/
addItemDataForLiteralNode (literalNode: ESTree.Literal & {value: string}): void;
/**
* @param {Literal} literalNode
* @returns {IStringArrayStorageItemData | undefined}
@@ -15,6 +15,7 @@ import { NodeTransformationStage } from '../../enums/node-transformers/NodeTrans
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeFactory } from '../../node/NodeFactory';
import { NumberNumericalExpressionAnalyzer } from '../../analyzers/number-numerical-expression-analyzer/NumberNumericalExpressionAnalyzer';
import { NumericalExpressionDataToNodeConverter } from '../../node/NumericalExpressionDataToNodeConverter';
/**
@@ -85,7 +86,10 @@ export class NumberToNumericalExpressionTransformer extends AbstractNodeTransfor
return literalNode;
}
const numberNumericalExpressionData: TNumberNumericalExpressionData = this.numberNumericalExpressionAnalyzer.analyze(literalNode.value);
const numberNumericalExpressionData: TNumberNumericalExpressionData = this.numberNumericalExpressionAnalyzer.analyze(
literalNode.value,
NumberNumericalExpressionAnalyzer.defaultAdditionalPartsCount
);
return NumericalExpressionDataToNodeConverter.convert(
numberNumericalExpressionData,
@@ -15,6 +15,7 @@ import { INumberNumericalExpressionAnalyzer } from '../../interfaces/analyzers/n
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorage } from '../../interfaces/storages/string-array-transformers/IStringArrayStorage';
import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { CustomCodeHelper } from '../../enums/custom-code-helpers/CustomCodeHelper';
@@ -45,6 +46,11 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
NodeTransformer.ScopeIdentifiersTransformer
];
/**
* @type {number}
*/
private static readonly comparisonExpressionAdditionalPartsCount: number = 7;
/**
* @type {INumberNumericalExpressionAnalyzer}
*/
@@ -55,6 +61,11 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
*/
private readonly stringArrayStorage: IStringArrayStorage;
/**
* @type {IStringArrayStorageAnalyzer}
*/
private readonly stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer;
/**
* @type {TCustomCodeHelperFactory}
*/
@@ -70,6 +81,7 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
* @param {IOptions} options
* @param {INodeTransformersRunner} transformersRunner
* @param {IStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
* @param {TCustomCodeHelperFactory} customCodeHelperFactory
* @param {INumberNumericalExpressionAnalyzer} numberNumericalExpressionAnalyzer
*/
@@ -78,6 +90,7 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.INodeTransformersRunner) transformersRunner: INodeTransformersRunner,
@inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
@inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
@inject(ServiceIdentifiers.INumberNumericalExpressionAnalyzer)
numberNumericalExpressionAnalyzer: INumberNumericalExpressionAnalyzer
@@ -85,11 +98,38 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
super(randomGenerator, options);
this.stringArrayStorage = stringArrayStorage;
this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
this.transformersRunner = transformersRunner;
this.customCodeHelperFactory = customCodeHelperFactory;
this.numberNumericalExpressionAnalyzer = numberNumericalExpressionAnalyzer;
}
/**
* Because this transformer runs BEFORE string array analyzer we can't check string array storage length.
* So we have to traverse over program node and check if it has any string literal node.
*
* @param {Program} programNode
* @returns {boolean}
*/
private static isProgramNodeHasStringLiterals (programNode: ESTree.Program): boolean {
let hasStringLiterals: boolean = false;
estraverse.traverse(programNode, {
enter: (node: ESTree.Node): estraverse.VisitorOption | void => {
if (
NodeGuards.isLiteralNode(node)
&& NodeLiteralUtils.isStringLiteralNode(node)
) {
hasStringLiterals = true;
return estraverse.VisitorOption.Break;
}
}
});
return hasStringLiterals;
}
/**
* @param {NodeTransformationStage} nodeTransformationStage
* @returns {IVisitor | null}
@@ -102,12 +142,16 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
switch (nodeTransformationStage) {
case NodeTransformationStage.StringArray:
return {
enter: (node: ESTree.Node): ESTree.Node | undefined => {
if (NodeGuards.isProgramNode(node)) {
this.transformNode(node);
enter: (node: ESTree.Node): ESTree.Node | estraverse.VisitorOption => {
if (!NodeGuards.isProgramNode(node)) {
return node;
}
return node;
if (!StringArrayRotateFunctionTransformer.isProgramNodeHasStringLiterals(node)) {
return estraverse.VisitorOption.Break;
}
return this.transformNode(node);
}
};
@@ -149,17 +193,21 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
estraverse.traverse(wrappedStringArrayRotateFunctionNode, {
enter: (node: ESTree.Node): void => {
if (
NodeGuards.isLiteralNode(node)
&& NodeLiteralUtils.isStringLiteralNode(node)
&& !/\d/.test(node.value)
!NodeGuards.isLiteralNode(node)
|| !NodeLiteralUtils.isStringLiteralNode(node)
) {
return;
}
if (/\d/.test(node.value)) {
this.stringArrayStorageAnalyzer.addItemDataForLiteralNode(node);
} else {
NodeMetadata.set(node, {ignoredNode: true});
}
}
});
NodeAppender.prepend(programNode, [stringArrayRotateFunctionNode]);
NodeUtils.parentizeNode(stringArrayRotateFunctionNode, programNode);
return programNode;
}
@@ -170,24 +218,28 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
private getStringArrayRotateFunctionNode (): TStatement {
const comparisonValue: number = this.randomGenerator.getRandomInteger(100000, 1_000_000);
const comparisonExpressionNumberNumericalExpressionData: TNumberNumericalExpressionData =
this.numberNumericalExpressionAnalyzer.analyze(comparisonValue);
this.numberNumericalExpressionAnalyzer.analyze(
comparisonValue,
StringArrayRotateFunctionTransformer.comparisonExpressionAdditionalPartsCount
);
const comparisonExpressionNode: ESTree.Expression = NumericalExpressionDataToNodeConverter.convert(
comparisonExpressionNumberNumericalExpressionData,
((number: number, isPositiveNumber) => {
const literalNode: ESTree.Literal = NodeFactory.literalNode(number.toString());
return NodeFactory.callExpressionNode(
NodeFactory.identifierNode('parseInt'),
[
isPositiveNumber
? literalNode
: NodeFactory.unaryExpressionNode(
'-',
literalNode
)
]
const literalNode: ESTree.Literal = NodeFactory.literalNode(
`${number}${this.randomGenerator.getRandomString(6)}`
);
const parseIntCallExpression: ESTree.CallExpression = NodeFactory.callExpressionNode(
NodeFactory.identifierNode('parseInt'),
[literalNode]
);
return isPositiveNumber
? parseIntCallExpression
: NodeFactory.unaryExpressionNode(
'-',
parseIntCallExpression
);
})
);
+1 -1
View File
@@ -299,7 +299,7 @@ export class Options implements IOptions {
*/
@IsNumber()
@ValidateIf((options: IOptions) => Boolean(options.splitStrings))
@Min(3)
@Min(1)
public readonly splitStringsChunkLength!: number;
/**