Use block scope instead node identifier

This commit is contained in:
sanex3339
2018-06-07 01:16:17 +03:00
parent 6311ccaf53
commit 19696ec33c
14 changed files with 29028 additions and 139 deletions
@@ -1,17 +1,19 @@
import * as ESTree from 'estree';
import { TNodeWithBlockScope } from '../../../../types/node/TNodeWithBlockScope';
import { IObfuscatingReplacer } from './IObfuscatingReplacer';
export interface IIdentifierObfuscatingReplacer extends IObfuscatingReplacer <ESTree.Identifier> {
/**
* @param {string} nodeValue
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
storeGlobalName (nodeValue: string, nodeIdentifier: number): void;
storeGlobalName (nodeValue: string, blockScopeNode: TNodeWithBlockScope): void;
/**
* @param {string} nodeValue
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
storeLocalName (nodeValue: string, nodeIdentifier: number): void;
storeLocalName (nodeValue: string, blockScopeNode: TNodeWithBlockScope): void;
}
@@ -1,10 +1,13 @@
import * as ESTree from 'estree';
import { TNodeWithBlockScope } from '../../../../types/node/TNodeWithBlockScope';
export interface IObfuscatingReplacer <T = ESTree.Node> {
/**
* @param {SimpleLiteral['value']} nodeValue
* @param {SimpleLiteral["value"]} nodeValue
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
* @returns {T}
*/
replace (nodeValue: ESTree.SimpleLiteral['value'], nodeIdentifier?: number): T;
replace (nodeValue: ESTree.SimpleLiteral['value'], blockScopeNode?: TNodeWithBlockScope, nodeIdentifier?: number): T;
}
@@ -1,27 +1,18 @@
import { inject, injectable, postConstruct } from 'inversify';
import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { IInitializable } from '../interfaces/IInitializable';
import { INodeTransformer } from '../interfaces/node-transformers/INodeTransformer';
import { IOptions } from '../interfaces/options/IOptions';
import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../interfaces/node-transformers/IVisitor';
import { initializable } from '../decorators/Initializable';
import { TransformationStage } from '../enums/node-transformers/TransformationStage';
@injectable()
export abstract class AbstractNodeTransformer implements INodeTransformer, IInitializable {
/**
* @type {number}
*/
@initializable()
protected nodeIdentifier!: number;
export abstract class AbstractNodeTransformer implements INodeTransformer {
/**
* @type {IOptions}
*/
@@ -44,11 +35,6 @@ export abstract class AbstractNodeTransformer implements INodeTransformer, IInit
this.options = options;
}
@postConstruct()
public initialize (): void {
this.nodeIdentifier = this.randomGenerator.getRandomInteger(0, 10000);
}
/**
* @param {TransformationStage} transformationStage
* @returns {IVisitor | null}
@@ -5,6 +5,7 @@ import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory';
import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer';
import { IOptions } from '../../interfaces/options/IOptions';
@@ -17,6 +18,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeMetadata } from '../../node/NodeMetadata';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -77,34 +79,40 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (catchClauseNode: ESTree.CatchClause, parentNode: ESTree.Node): ESTree.Node {
const nodeIdentifier: number = this.nodeIdentifier++;
const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(catchClauseNode)[0];
this.storeCatchClauseParam(catchClauseNode, nodeIdentifier);
this.replaceCatchClauseParam(catchClauseNode, nodeIdentifier);
this.storeCatchClauseParam(catchClauseNode, blockScopeNode);
this.replaceCatchClauseParam(catchClauseNode, blockScopeNode);
return catchClauseNode;
}
/**
* @param {CatchClause} catchClauseNode
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
private storeCatchClauseParam (catchClauseNode: ESTree.CatchClause, nodeIdentifier: number): void {
private storeCatchClauseParam (
catchClauseNode: ESTree.CatchClause,
blockScopeNode: TNodeWithBlockScope
): void {
if (NodeGuards.isIdentifierNode(catchClauseNode.param)) {
this.identifierObfuscatingReplacer.storeLocalName(catchClauseNode.param.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeLocalName(catchClauseNode.param.name, blockScopeNode);
}
}
/**
* @param {CatchClause} catchClauseNode
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
private replaceCatchClauseParam (catchClauseNode: ESTree.CatchClause, nodeIdentifier: number): void {
private replaceCatchClauseParam (
catchClauseNode: ESTree.CatchClause,
blockScopeNode: TNodeWithBlockScope
): void {
estraverse.replace(catchClauseNode, {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
if (parentNode && NodeGuards.isReplaceableIdentifierNode(node, parentNode)) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, nodeIdentifier);
.replace(node.name, blockScopeNode);
const newIdentifierName: string = newIdentifier.name;
if (node.name !== newIdentifierName) {
@@ -90,7 +90,6 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (classDeclarationNode: ESTree.ClassDeclaration, parentNode: ESTree.Node): ESTree.Node {
const nodeIdentifier: number = this.nodeIdentifier++;
const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(classDeclarationNode)[0];
const isGlobalDeclaration: boolean = blockScopeNode.type === NodeType.Program;
@@ -98,13 +97,13 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
return classDeclarationNode;
}
this.storeClassName(classDeclarationNode, isGlobalDeclaration, nodeIdentifier);
this.storeClassName(classDeclarationNode, blockScopeNode, isGlobalDeclaration);
// check for cached identifiers for current scope node. If exist - loop through them.
if (this.replaceableIdentifiers.has(blockScopeNode)) {
this.replaceScopeCachedIdentifiers(blockScopeNode, nodeIdentifier);
this.replaceScopeCachedIdentifiers(blockScopeNode);
} else {
this.replaceScopeIdentifiers(blockScopeNode, nodeIdentifier);
this.replaceScopeIdentifiers(blockScopeNode);
}
return classDeclarationNode;
@@ -112,31 +111,31 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
/**
* @param {ClassDeclaration} classDeclarationNode
* @param {TNodeWithBlockScope} blockScopeNode
* @param {boolean} isGlobalDeclaration
* @param {number} nodeIdentifier
*/
private storeClassName (
classDeclarationNode: ESTree.ClassDeclaration,
isGlobalDeclaration: boolean,
nodeIdentifier: number
blockScopeNode: TNodeWithBlockScope,
isGlobalDeclaration: boolean
): void {
if (isGlobalDeclaration) {
this.identifierObfuscatingReplacer.storeGlobalName(classDeclarationNode.id.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeGlobalName(classDeclarationNode.id.name, blockScopeNode);
} else {
this.identifierObfuscatingReplacer.storeLocalName(classDeclarationNode.id.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeLocalName(classDeclarationNode.id.name, blockScopeNode);
}
}
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeCachedIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
const cachedReplaceableIdentifiers: ESTree.Identifier[] = <ESTree.Identifier[]>this.replaceableIdentifiers.get(blockScopeNode);
private replaceScopeCachedIdentifiers (blockScopeNode: TNodeWithBlockScope): void {
const cachedReplaceableIdentifiers: ESTree.Identifier[] =
<ESTree.Identifier[]>this.replaceableIdentifiers.get(blockScopeNode);
cachedReplaceableIdentifiers.forEach((replaceableIdentifier: ESTree.Identifier) => {
const newReplaceableIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(replaceableIdentifier.name, nodeIdentifier);
.replace(replaceableIdentifier.name, blockScopeNode);
replaceableIdentifier.name = newReplaceableIdentifier.name;
NodeMetadata.set(replaceableIdentifier, { renamedIdentifier: true });
@@ -145,9 +144,8 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope): void {
const storedReplaceableIdentifiers: ESTree.Identifier[] = [];
estraverse.replace(blockScopeNode, {
@@ -158,7 +156,7 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
&& !NodeMetadata.isRenamedIdentifier(node)
) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, nodeIdentifier);
.replace(node.name, blockScopeNode);
const newIdentifierName: string = newIdentifier.name;
if (node.name !== newIdentifierName) {
@@ -92,7 +92,6 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (functionDeclarationNode: ESTree.FunctionDeclaration, parentNode: ESTree.Node): ESTree.Node {
const nodeIdentifier: number = this.nodeIdentifier++;
const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(functionDeclarationNode)[0];
const isGlobalDeclaration: boolean = blockScopeNode.type === NodeType.Program;
@@ -100,13 +99,13 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
return functionDeclarationNode;
}
this.storeFunctionName(functionDeclarationNode, isGlobalDeclaration, nodeIdentifier);
this.storeFunctionName(functionDeclarationNode, blockScopeNode, isGlobalDeclaration);
// check for cached identifiers for current scope node. If exist - loop through them.
if (this.replaceableIdentifiers.has(blockScopeNode)) {
this.replaceScopeCachedIdentifiers(functionDeclarationNode, blockScopeNode, nodeIdentifier);
this.replaceScopeCachedIdentifiers(functionDeclarationNode, blockScopeNode);
} else {
this.replaceScopeIdentifiers(blockScopeNode, nodeIdentifier);
this.replaceScopeIdentifiers(blockScopeNode);
}
return functionDeclarationNode;
@@ -114,32 +113,31 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
/**
* @param {FunctionDeclaration} functionDeclarationNode
* @param {TNodeWithBlockScope} blockScopeNode
* @param {boolean} isGlobalDeclaration
* @param {number} nodeIdentifier
*/
private storeFunctionName (
functionDeclarationNode: ESTree.FunctionDeclaration,
isGlobalDeclaration: boolean,
nodeIdentifier: number
blockScopeNode: TNodeWithBlockScope,
isGlobalDeclaration: boolean
): void {
if (isGlobalDeclaration) {
this.identifierObfuscatingReplacer.storeGlobalName(functionDeclarationNode.id.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeGlobalName(functionDeclarationNode.id.name, blockScopeNode);
} else {
this.identifierObfuscatingReplacer.storeLocalName(functionDeclarationNode.id.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeLocalName(functionDeclarationNode.id.name, blockScopeNode);
}
}
/**
* @param {FunctionDeclaration} functionDeclarationNode
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeCachedIdentifiers (
functionDeclarationNode: ESTree.FunctionDeclaration,
blockScopeNode: TNodeWithBlockScope,
nodeIdentifier: number
blockScopeNode: TNodeWithBlockScope
): void {
const cachedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames | undefined = this.replaceableIdentifiers.get(blockScopeNode);
const cachedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames | undefined =
this.replaceableIdentifiers.get(blockScopeNode);
if (!cachedReplaceableIdentifiersNamesMap) {
return;
@@ -157,7 +155,7 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
for (let i: number = 0; i < cachedReplaceableIdentifierLength; i++) {
const replaceableIdentifier: ESTree.Identifier = cachedReplaceableIdentifiers[i];
const newReplaceableIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(replaceableIdentifier.name, nodeIdentifier);
.replace(replaceableIdentifier.name, blockScopeNode);
replaceableIdentifier.name = newReplaceableIdentifier.name;
NodeMetadata.set(replaceableIdentifier, { renamedIdentifier: true });
@@ -166,9 +164,8 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope): void {
const storedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames = new Map();
estraverse.replace(blockScopeNode, {
@@ -179,14 +176,15 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
&& !NodeMetadata.isRenamedIdentifier(node)
) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, nodeIdentifier);
.replace(node.name, blockScopeNode);
const newIdentifierName: string = newIdentifier.name;
if (node.name !== newIdentifierName) {
node.name = newIdentifierName;
NodeMetadata.set(node, { renamedIdentifier: true });
} else {
const storedReplaceableIdentifiers: ESTree.Identifier[] = storedReplaceableIdentifiersNamesMap.get(node.name) || [];
const storedReplaceableIdentifiers: ESTree.Identifier[] =
storedReplaceableIdentifiersNamesMap.get(node.name) || [];
storedReplaceableIdentifiers.push(node);
storedReplaceableIdentifiersNamesMap.set(node.name, storedReplaceableIdentifiers);
@@ -5,6 +5,7 @@ import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory';
import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer';
import { IOptions } from '../../interfaces/options/IOptions';
@@ -17,6 +18,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeMetadata } from '../../node/NodeMetadata';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -83,19 +85,21 @@ export class FunctionTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (functionNode: ESTree.Function, parentNode: ESTree.Node): ESTree.Node {
const nodeIdentifier: number = this.nodeIdentifier++;
const blockScopeNode: TNodeWithBlockScope = NodeGuards.isBlockStatementNode(functionNode.body)
? functionNode.body
: NodeUtils.getBlockScopesOfNode(functionNode.body)[0];
this.storeFunctionParams(functionNode, nodeIdentifier);
this.replaceFunctionParams(functionNode, nodeIdentifier);
this.storeFunctionParams(functionNode, blockScopeNode);
this.replaceFunctionParams(functionNode, blockScopeNode);
return functionNode;
}
/**
* @param {Function} functionNode
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
private storeFunctionParams (functionNode: ESTree.Function, nodeIdentifier: number): void {
private storeFunctionParams (functionNode: ESTree.Function, blockScopeNode: TNodeWithBlockScope): void {
functionNode.params
.forEach((paramsNode: ESTree.Node) => {
estraverse.traverse(paramsNode, {
@@ -105,13 +109,13 @@ export class FunctionTransformer extends AbstractNodeTransformer {
}
if (NodeGuards.isAssignmentPatternNode(node) && NodeGuards.isIdentifierNode(node.left)) {
this.identifierObfuscatingReplacer.storeLocalName(node.left.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeLocalName(node.left.name, blockScopeNode);
return estraverse.VisitorOption.Skip;
}
if (NodeGuards.isIdentifierNode(node)) {
this.identifierObfuscatingReplacer.storeLocalName(node.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeLocalName(node.name, blockScopeNode);
}
}
});
@@ -137,9 +141,9 @@ export class FunctionTransformer extends AbstractNodeTransformer {
/**
* @param {Function} functionNode
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
private replaceFunctionParams (functionNode: ESTree.Function, nodeIdentifier: number): void {
private replaceFunctionParams (functionNode: ESTree.Function, blockScopeNode: TNodeWithBlockScope): void {
const ignoredIdentifierNamesSet: Set<string> = new Set();
const replaceVisitor: estraverse.Visitor = {
@@ -153,7 +157,8 @@ export class FunctionTransformer extends AbstractNodeTransformer {
NodeGuards.isReplaceableIdentifierNode(node, parentNode) &&
!ignoredIdentifierNamesSet.has(node.name)
) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer.replace(node.name, nodeIdentifier);
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, blockScopeNode);
const newIdentifierName: string = newIdentifier.name;
if (node.name !== newIdentifierName) {
@@ -95,45 +95,47 @@ export class ImportDeclarationTransformer extends AbstractNodeTransformer {
* @returns {Node}
*/
public transformNode (importDeclarationNode: ESTree.ImportDeclaration, parentNode: ESTree.Node): ESTree.Node {
const nodeIdentifier: number = this.nodeIdentifier++;
const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(importDeclarationNode)[0];
this.storeImportSpecifierNames(importDeclarationNode, nodeIdentifier);
this.storeImportSpecifierNames(importDeclarationNode, blockScopeNode);
// check for cached identifiers for current scope node. If exist - loop through them.
if (this.replaceableIdentifiers.has(blockScopeNode)) {
this.replaceScopeCachedIdentifiers(blockScopeNode, nodeIdentifier);
this.replaceScopeCachedIdentifiers(blockScopeNode);
} else {
this.replaceScopeIdentifiers(blockScopeNode, nodeIdentifier);
this.replaceScopeIdentifiers(blockScopeNode);
}
return importDeclarationNode;
}
/**
* @param {ImportDefaultSpecifier | ImportNamespaceSpecifier} importDeclarationNode
* @param {number} nodeIdentifier
* @param {ImportDeclaration} importDeclarationNode
* @param {TNodeWithBlockScope} blockScopeNode
*/
private storeImportSpecifierNames (importDeclarationNode: ESTree.ImportDeclaration, nodeIdentifier: number): void {
private storeImportSpecifierNames (
importDeclarationNode: ESTree.ImportDeclaration,
blockScopeNode: TNodeWithBlockScope
): void {
importDeclarationNode.specifiers.forEach((importSpecifierNode: TImportSpecifier) => {
if (ImportDeclarationTransformer.isProhibitedImportSpecifierNode(importSpecifierNode)) {
return;
}
this.identifierObfuscatingReplacer.storeGlobalName(importSpecifierNode.local.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeGlobalName(importSpecifierNode.local.name, blockScopeNode);
});
}
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeCachedIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
const cachedReplaceableIdentifiers: ESTree.Identifier[] = <ESTree.Identifier[]>this.replaceableIdentifiers.get(blockScopeNode);
private replaceScopeCachedIdentifiers (blockScopeNode: TNodeWithBlockScope): void {
const cachedReplaceableIdentifiers: ESTree.Identifier[] =
<ESTree.Identifier[]>this.replaceableIdentifiers.get(blockScopeNode);
cachedReplaceableIdentifiers.forEach((replaceableIdentifier: ESTree.Identifier) => {
const newReplaceableIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(replaceableIdentifier.name, nodeIdentifier);
.replace(replaceableIdentifier.name, blockScopeNode);
replaceableIdentifier.name = newReplaceableIdentifier.name;
NodeMetadata.set(replaceableIdentifier, { renamedIdentifier: true });
@@ -142,9 +144,8 @@ export class ImportDeclarationTransformer extends AbstractNodeTransformer {
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope, nodeIdentifier: number): void {
private replaceScopeIdentifiers (blockScopeNode: TNodeWithBlockScope): void {
const storedReplaceableIdentifiers: ESTree.Identifier[] = [];
estraverse.replace(blockScopeNode, {
@@ -155,7 +156,7 @@ export class ImportDeclarationTransformer extends AbstractNodeTransformer {
&& !NodeMetadata.isRenamedIdentifier(node)
) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, nodeIdentifier);
.replace(node.name, blockScopeNode);
const newIdentifierName: string = newIdentifier.name;
if (node.name !== newIdentifierName) {
@@ -16,6 +16,8 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
import { TNodeWithBlockScope } from '../../types/node/TNodeWithBlockScope';
import { NodeUtils } from '../../node/NodeUtils';
/**
* replaces:
@@ -84,32 +86,38 @@ export class LabeledStatementTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (labeledStatementNode: ESTree.LabeledStatement, parentNode: ESTree.Node): ESTree.Node {
const nodeIdentifier: number = this.nodeIdentifier++;
const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(labeledStatementNode)[0];
this.storeLabeledStatementName(labeledStatementNode, nodeIdentifier);
this.replaceLabeledStatementName(labeledStatementNode, nodeIdentifier);
this.storeLabeledStatementName(labeledStatementNode, blockScopeNode);
this.replaceLabeledStatementName(labeledStatementNode, blockScopeNode);
return labeledStatementNode;
}
/**
* @param {LabeledStatement} labeledStatementNode
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
private storeLabeledStatementName (labeledStatementNode: ESTree.LabeledStatement, nodeIdentifier: number): void {
this.identifierObfuscatingReplacer.storeLocalName(labeledStatementNode.label.name, nodeIdentifier);
private storeLabeledStatementName (
labeledStatementNode: ESTree.LabeledStatement,
blockScopeNode: TNodeWithBlockScope
): void {
this.identifierObfuscatingReplacer.storeLocalName(labeledStatementNode.label.name, blockScopeNode);
}
/**
* @param {LabeledStatement} labeledStatementNode
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
private replaceLabeledStatementName (labeledStatementNode: ESTree.LabeledStatement, nodeIdentifier: number): void {
private replaceLabeledStatementName (
labeledStatementNode: ESTree.LabeledStatement,
blockScopeNode: TNodeWithBlockScope
): void {
estraverse.replace(labeledStatementNode, {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
if (parentNode && NodeGuards.isLabelIdentifierNode(node, parentNode)) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, nodeIdentifier);
.replace(node.name, blockScopeNode);
node.name = newIdentifier.name;
}
@@ -100,18 +100,17 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
return variableDeclarationNode;
}
const nodeIdentifier: number = this.nodeIdentifier++;
const scopeNode: ESTree.Node = variableDeclarationNode.kind === 'var'
? blockScopeNode
: parentNode;
this.storeVariableNames(variableDeclarationNode, isGlobalDeclaration, nodeIdentifier);
this.storeVariableNames(variableDeclarationNode, blockScopeNode, isGlobalDeclaration);
// check for cached identifiers for current scope node. If exist - loop through them.
if (this.replaceableIdentifiers.has(scopeNode)) {
this.replaceScopeCachedIdentifiers(variableDeclarationNode, scopeNode, nodeIdentifier);
this.replaceScopeCachedIdentifiers(variableDeclarationNode, blockScopeNode, scopeNode);
} else {
this.replaceScopeIdentifiers(scopeNode, nodeIdentifier);
this.replaceScopeIdentifiers(scopeNode, blockScopeNode);
}
return variableDeclarationNode;
@@ -119,34 +118,35 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
/**
* @param {VariableDeclaration} variableDeclarationNode
* @param {TNodeWithBlockScope} blockScopeNode
* @param {boolean} isGlobalDeclaration
* @param {number} nodeIdentifier
*/
private storeVariableNames (
variableDeclarationNode: ESTree.VariableDeclaration,
isGlobalDeclaration: boolean,
nodeIdentifier: number
blockScopeNode: TNodeWithBlockScope,
isGlobalDeclaration: boolean
): void {
this.traverseDeclarationIdentifiers(variableDeclarationNode, (identifierNode: ESTree.Identifier) => {
if (isGlobalDeclaration) {
this.identifierObfuscatingReplacer.storeGlobalName(identifierNode.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeGlobalName(identifierNode.name, blockScopeNode);
} else {
this.identifierObfuscatingReplacer.storeLocalName(identifierNode.name, nodeIdentifier);
this.identifierObfuscatingReplacer.storeLocalName(identifierNode.name, blockScopeNode);
}
});
}
/**
* @param {VariableDeclaration} variableDeclarationNode
* @param {TNodeWithBlockScope} blockScopeNode
* @param {Node} scopeNode
* @param {number} nodeIdentifier
*/
private replaceScopeCachedIdentifiers (
variableDeclarationNode: ESTree.VariableDeclaration,
scopeNode: ESTree.Node,
nodeIdentifier: number
blockScopeNode: TNodeWithBlockScope,
scopeNode: ESTree.Node
): void {
const cachedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames | undefined = this.replaceableIdentifiers.get(scopeNode);
const cachedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames | undefined =
this.replaceableIdentifiers.get(scopeNode);
if (!cachedReplaceableIdentifiersNamesMap) {
return;
@@ -159,7 +159,8 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
});
identifierNames.forEach((identifierName: string) => {
const cachedReplaceableIdentifiers: ESTree.Identifier[] | undefined = cachedReplaceableIdentifiersNamesMap.get(identifierName);
const cachedReplaceableIdentifiers: ESTree.Identifier[] | undefined =
cachedReplaceableIdentifiersNamesMap.get(identifierName);
if (!cachedReplaceableIdentifiers) {
return;
@@ -175,7 +176,7 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
}
const newReplaceableIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(replaceableIdentifier.name, nodeIdentifier);
.replace(replaceableIdentifier.name, blockScopeNode);
replaceableIdentifier.name = newReplaceableIdentifier.name;
NodeMetadata.set(replaceableIdentifier, { renamedIdentifier: true });
@@ -184,27 +185,29 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
}
/**
* @param {NodeGuards} blockScopeNode
* @param {number} nodeIdentifier
* @param {Node} scopeNode
* @param {TNodeWithBlockScope} blockScopeNode
*/
private replaceScopeIdentifiers (blockScopeNode: ESTree.Node, nodeIdentifier: number): void {
private replaceScopeIdentifiers (scopeNode: ESTree.Node, blockScopeNode: TNodeWithBlockScope): void {
const storedReplaceableIdentifiersNamesMap: TReplaceableIdentifiersNames = new Map();
estraverse.replace(blockScopeNode, {
estraverse.replace(scopeNode, {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
if (
parentNode
&& NodeGuards.isReplaceableIdentifierNode(node, parentNode)
&& !NodeMetadata.isRenamedIdentifier(node)
) {
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer.replace(node.name, nodeIdentifier);
const newIdentifier: ESTree.Identifier = this.identifierObfuscatingReplacer
.replace(node.name, blockScopeNode);
const newIdentifierName: string = newIdentifier.name;
if (node.name !== newIdentifierName) {
node.name = newIdentifierName;
NodeMetadata.set(node, { renamedIdentifier: true });
} else {
const storedReplaceableIdentifiers: ESTree.Identifier[] = storedReplaceableIdentifiersNamesMap.get(node.name) || [];
const storedReplaceableIdentifiers: ESTree.Identifier[] =
storedReplaceableIdentifiersNamesMap.get(node.name) || [];
storedReplaceableIdentifiers.push(node);
storedReplaceableIdentifiersNamesMap.set(node.name, storedReplaceableIdentifiers);
@@ -213,7 +216,7 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
}
});
this.replaceableIdentifiers.set(blockScopeNode, storedReplaceableIdentifiersNamesMap);
this.replaceableIdentifiers.set(scopeNode, storedReplaceableIdentifiersNamesMap);
}
/**
@@ -3,6 +3,8 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TNodeWithBlockScope } from '../../../types/node/TNodeWithBlockScope';
import { IObfuscatingReplacer } from '../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
import { IOptions } from '../../../interfaces/options/IOptions';
@@ -23,9 +25,9 @@ export abstract class AbstractObfuscatingReplacer implements IObfuscatingReplace
}
/**
* @param {SimpleLiteral['value']} nodeValue
* @param {number} nodeIdentifier
* @param {SimpleLiteral["value"]} nodeValue
* @param {TNodeWithBlockScope} blockScopeNode
* @returns {Node}
*/
public abstract replace (nodeValue: ESTree.SimpleLiteral['value'], nodeIdentifier?: number): ESTree.Node;
public abstract replace (nodeValue: ESTree.SimpleLiteral['value'], blockScopeNode?: TNodeWithBlockScope): ESTree.Node;
}
@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TIdentifierNamesGeneratorFactory } from '../../../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { TNodeWithBlockScope } from '../../../../types/node/TNodeWithBlockScope';
import { IIdentifierNamesGenerator } from '../../../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
import { IIdentifierObfuscatingReplacer } from '../../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer';
@@ -20,9 +21,9 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
private readonly identifierNamesGenerator: IIdentifierNamesGenerator;
/**
* @type {Map<string, string>}
* @type {Map<TNodeWithBlockScope, Map<string, string>>}
*/
private readonly namesMap: Map<string, string> = new Map();
private readonly blockScopesMap: Map<TNodeWithBlockScope, Map<string, string>> = new Map();
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
@@ -40,14 +41,16 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
/**
* @param {string} nodeValue
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
* @returns {Identifier}
*/
public replace (nodeValue: string, nodeIdentifier: number): ESTree.Identifier {
const mapKey: string = `${nodeValue}-${String(nodeIdentifier)}`;
public replace (nodeValue: string, blockScopeNode: TNodeWithBlockScope): ESTree.Identifier {
if (this.blockScopesMap.has(blockScopeNode)) {
const namesMap: Map<string, string> = <Map<string, string>>this.blockScopesMap.get(blockScopeNode);
if (this.namesMap.has(mapKey)) {
nodeValue = <string>this.namesMap.get(mapKey);
if (namesMap.has(nodeValue)) {
nodeValue = <string>namesMap.get(nodeValue);
}
}
return NodeFactory.identifierNode(nodeValue);
@@ -58,16 +61,22 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
* Reserved name will be ignored.
*
* @param {string} nodeName
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
public storeGlobalName (nodeName: string, nodeIdentifier: number): void {
public storeGlobalName (nodeName: string, blockScopeNode: TNodeWithBlockScope): void {
if (this.isReservedName(nodeName)) {
return;
}
const identifierName: string = this.identifierNamesGenerator.generateWithPrefix();
this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, identifierName);
if (!this.blockScopesMap.has(blockScopeNode)) {
this.blockScopesMap.set(blockScopeNode, new Map());
}
const namesMap: Map<string, string> = <Map<string, string>>this.blockScopesMap.get(blockScopeNode);
namesMap.set(nodeName, identifierName);
}
/**
@@ -75,16 +84,22 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
* Reserved name will be ignored.
*
* @param {string} nodeName
* @param {number} nodeIdentifier
* @param {TNodeWithBlockScope} blockScopeNode
*/
public storeLocalName (nodeName: string, nodeIdentifier: number): void {
public storeLocalName (nodeName: string, blockScopeNode: TNodeWithBlockScope): void {
if (this.isReservedName(nodeName)) {
return;
}
const identifierName: string = this.identifierNamesGenerator.generate();
this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, identifierName);
if (!this.blockScopesMap.has(blockScopeNode)) {
this.blockScopesMap.set(blockScopeNode, new Map());
}
const namesMap: Map<string, string> = <Map<string, string>>this.blockScopesMap.get(blockScopeNode);
namesMap.set(nodeName, identifierName);
}
/**