Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Change Log

v0.19.3
---
* The `splitStrings` option now correctly works with `transformObjectKeys` option
* Internal `TransformersRunner` rework to support topological sort of node transformers

v0.19.2
---
* The `splitStrings` option now correctly splits strings inside objects
Expand Down
6 changes: 3 additions & 3 deletions dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "0.19.2",
"version": "0.19.3",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
2 changes: 2 additions & 0 deletions src/container/ServiceIdentifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ export enum ServiceIdentifiers {
IIdentifierNamesGenerator = 'IIdentifierNamesGenerator',
IIdentifierObfuscatingReplacer = 'IIdentifierObfuscatingReplacer',
IJavaScriptObfuscator = 'IJavaScriptObfuscator',
ILevelledTopologicalSorter = 'ILevelledTopologicalSorter',
ILogger = 'ILogger',
INodeGuard = 'INodeGuard',
INodeTransformer = 'INodeTransformer',
INodeTransformerNamesGroupsBuilder = 'INodeTransformerNamesGroupsBuilder',
IObfuscationEventEmitter = 'IObfuscationEventEmitter',
IObfuscatedCode = 'IObfuscatedCode',
IOptions = 'IOptions',
Expand Down
13 changes: 13 additions & 0 deletions src/container/modules/utils/UtilsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { IArrayUtils } from '../../../interfaces/utils/IArrayUtils';
import { ICryptUtils } from '../../../interfaces/utils/ICryptUtils';
import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
import { ILevelledTopologicalSorter } from '../../../interfaces/utils/ILevelledTopologicalSorter';
import { INodeTransformerNamesGroupsBuilder } from '../../../interfaces/utils/INodeTransformerNamesGroupsBuilder';
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';

import { ArrayUtils } from '../../../utils/ArrayUtils';
import { CryptUtils } from '../../../utils/CryptUtils';
import { EscapeSequenceEncoder } from '../../../utils/EscapeSequenceEncoder';
import { LevelledTopologicalSorter } from '../../../utils/LevelledTopologicalSorter';
import { NodeTransformerNamesGroupsBuilder } from '../../../utils/NodeTransformerNamesGroupsBuilder';
import { RandomGenerator } from '../../../utils/RandomGenerator';

export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
Expand All @@ -31,4 +35,13 @@ export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind
bind<IEscapeSequenceEncoder>(ServiceIdentifiers.IEscapeSequenceEncoder)
.to(EscapeSequenceEncoder)
.inSingletonScope();

// levelled topological sorter
bind<ILevelledTopologicalSorter>(ServiceIdentifiers.ILevelledTopologicalSorter)
.to(LevelledTopologicalSorter);

// node transformer names groups builder
bind<INodeTransformerNamesGroupsBuilder>(ServiceIdentifiers.INodeTransformerNamesGroupsBuilder)
.to(NodeTransformerNamesGroupsBuilder)
.inSingletonScope();
});
6 changes: 6 additions & 0 deletions src/interfaces/node-transformers/INodeTransformer.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import * as ESTree from 'estree';

import { IVisitor } from './IVisitor';

import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
import { TransformationStage } from '../../enums/node-transformers/TransformationStage';

export interface INodeTransformer {
/**
* @type {NodeTransformer[] | undefined}
*/
runAfter?: NodeTransformer[];

/**
* @param {TransformationStage} transformationStage
* @returns {IVisitor | null}
Expand Down
21 changes: 21 additions & 0 deletions src/interfaces/utils/ILevelledTopologicalSorter.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface ILevelledTopologicalSorter <TValue extends string = string> {
/**
* @param {TValue} precedent
* @param {TValue | null} consequent
* @returns {this}
*/
add (
precedent: TValue,
consequent?: TValue | null
): this;

/**
* @returns {TValue[]}
*/
sort (): TValue[];

/**
* @returns {TValue[][]}
*/
sortByGroups (): TValue[][];
}
11 changes: 11 additions & 0 deletions src/interfaces/utils/INodeTransformerNamesGroupsBuilder.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { TNormalizedNodeTransformers } from '../../types/node-transformers/TNormalizedNodeTransformers';

import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';

export interface INodeTransformerNamesGroupsBuilder {
/**
* @param {TNormalizedNodeTransformers} normalizedNodeTransformers
* @returns {NodeTransformer[][]}
*/
build (normalizedNodeTransformers: TNormalizedNodeTransformers): NodeTransformer[][];
}
6 changes: 6 additions & 0 deletions src/node-transformers/AbstractNodeTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ import { IOptions } from '../interfaces/options/IOptions';
import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../interfaces/node-transformers/IVisitor';

import { NodeTransformer } from '../enums/node-transformers/NodeTransformer';
import { TransformationStage } from '../enums/node-transformers/TransformationStage';

@injectable()
export abstract class AbstractNodeTransformer implements INodeTransformer {
/**
* @type {NodeTransformer[] | undefined}
*/
public readonly runAfter: NodeTransformer[] | undefined;

/**
* @type {IOptions}
*/
Expand Down
99 changes: 74 additions & 25 deletions src/node-transformers/TransformersRunner.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { inject, injectable } from 'inversify';

import { ServiceIdentifiers } from '../container/ServiceIdentifiers';

import * as estraverse from 'estraverse';
import * as ESTree from 'estree';

import { TNodeTransformerFactory } from '../types/container/node-transformers/TNodeTransformerFactory';
import { TNormalizedNodeTransformers } from '../types/node-transformers/TNormalizedNodeTransformers';
import { TTransformersRunnerData } from '../types/node-transformers/TTransformersRunnerData';
import { TVisitorDirection } from '../types/node-transformers/TVisitorDirection';
import { TVisitorFunction } from '../types/node-transformers/TVisitorFunction';
import { TVisitorResult } from '../types/node-transformers/TVisitorResult';

import { INodeTransformer } from '../interfaces/node-transformers/INodeTransformer';
import { INodeTransformerNamesGroupsBuilder } from '../interfaces/utils/INodeTransformerNamesGroupsBuilder';
import { ITransformersRunner } from '../interfaces/node-transformers/ITransformersRunner';
import { IVisitor } from '../interfaces/node-transformers/IVisitor';

Expand All @@ -21,69 +26,113 @@ import { NodeMetadata } from '../node/NodeMetadata';

@injectable()
export class TransformersRunner implements ITransformersRunner {
/**
* @type {Map<NodeTransformer[], TTransformersRunnerData>}
*/
private readonly cachedNodeTransformersData: Map<NodeTransformer[], TTransformersRunnerData> = new Map();

/**
* @type {TNodeTransformerFactory}
*/
private readonly nodeTransformerFactory: TNodeTransformerFactory;

/**
* @type {INodeTransformerNamesGroupsBuilder}
*/
private readonly nodeTransformerNamesGroupsBuilder: INodeTransformerNamesGroupsBuilder;

/**
* @param {TNodeTransformerFactory} nodeTransformerFactory
* @param {INodeTransformerNamesGroupsBuilder} nodeTransformerNamesGroupsBuilder
*/
constructor (
@inject(ServiceIdentifiers.Factory__INodeTransformer) nodeTransformerFactory: TNodeTransformerFactory,
@inject(ServiceIdentifiers.Factory__INodeTransformer)
nodeTransformerFactory: TNodeTransformerFactory,
@inject(ServiceIdentifiers.INodeTransformerNamesGroupsBuilder)
nodeTransformerNamesGroupsBuilder: INodeTransformerNamesGroupsBuilder,
) {
this.nodeTransformerFactory = nodeTransformerFactory;
this.nodeTransformerNamesGroupsBuilder = nodeTransformerNamesGroupsBuilder;
}

/**
* @param {T} astTree
* @param {NodeTransformer[]} nodeTransformers
* @param {NodeTransformer[]} nodeTransformerNames
* @param {TransformationStage} transformationStage
* @returns {T}
*/
public transform <T extends ESTree.Node = ESTree.Program> (
astTree: T,
nodeTransformers: NodeTransformer[],
nodeTransformerNames: NodeTransformer[],
transformationStage: TransformationStage
): T {
if (!nodeTransformers.length) {
if (!nodeTransformerNames.length) {
return astTree;
}

const enterVisitors: IVisitor[] = [];
const leaveVisitors: IVisitor[] = [];
const nodeTransformersLength: number = nodeTransformers.length;
let normalizedNodeTransformers: TNormalizedNodeTransformers;
let nodeTransformerNamesGroups: NodeTransformer[][];

if (!this.cachedNodeTransformersData.has(nodeTransformerNames)) {
normalizedNodeTransformers = this.buildNormalizedNodeTransformers(nodeTransformerNames);
nodeTransformerNamesGroups = this.nodeTransformerNamesGroupsBuilder.build(normalizedNodeTransformers);
this.cachedNodeTransformersData.set(nodeTransformerNames, [normalizedNodeTransformers, nodeTransformerNamesGroups]);
} else {
[
normalizedNodeTransformers,
nodeTransformerNamesGroups
] = <TTransformersRunnerData>this.cachedNodeTransformersData.get(nodeTransformerNames);
}

let visitor: IVisitor | null;
for (const nodeTransformerNamesGroup of nodeTransformerNamesGroups) {
const enterVisitors: IVisitor[] = [];
const leaveVisitors: IVisitor[] = [];

for (let i: number = 0; i < nodeTransformersLength; i++) {
visitor = this.nodeTransformerFactory(nodeTransformers[i]).getVisitor(transformationStage);
for (const nodeTransformerName of nodeTransformerNamesGroup) {
const nodeTransformer: INodeTransformer = normalizedNodeTransformers[nodeTransformerName];
const visitor: IVisitor | null = nodeTransformer.getVisitor(transformationStage);

if (!visitor) {
continue;
}
if (!visitor) {
continue;
}

if (visitor.enter) {
enterVisitors.push({ enter: visitor.enter });
if (visitor.enter) {
enterVisitors.push({ enter: visitor.enter });
}

if (visitor.leave) {
leaveVisitors.push({ leave: visitor.leave });
}
}

if (visitor.leave) {
leaveVisitors.push({ leave: visitor.leave });
if (!enterVisitors.length && !leaveVisitors.length) {
continue;
}
}

if (!enterVisitors.length && !leaveVisitors.length) {
return astTree;
estraverse.replace(astTree, {
enter: this.mergeVisitorsForDirection(enterVisitors, VisitorDirection.Enter),
leave: this.mergeVisitorsForDirection(leaveVisitors, VisitorDirection.Leave)
});
}

estraverse.replace(astTree, {
enter: this.mergeVisitorsForDirection(enterVisitors, VisitorDirection.Enter),
leave: this.mergeVisitorsForDirection(leaveVisitors, VisitorDirection.Leave)
});

return astTree;
}

/**
* @param {NodeTransformer[]} nodeTransformerNames
* @returns {TNormalizedNodeTransformers}
*/
private buildNormalizedNodeTransformers (nodeTransformerNames: NodeTransformer[]): TNormalizedNodeTransformers {
return nodeTransformerNames
.reduce<TNormalizedNodeTransformers>(
(acc: TNormalizedNodeTransformers, nodeTransformerName: NodeTransformer) => ({
...acc,
[nodeTransformerName]: this.nodeTransformerFactory(nodeTransformerName)
}),
{}
);
}

/**
* @param {IVisitor[]} visitors
* @param {TVisitorDirection} direction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';

import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
import { TransformationStage } from '../../enums/node-transformers/TransformationStage';

import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
Expand All @@ -18,6 +19,14 @@ import { NodeGuards } from '../../node/NodeGuards';
*/
@injectable()
export class SplitStringTransformer extends AbstractNodeTransformer {
/**
* @type {NodeTransformer[]}
*/
public runAfter: NodeTransformer[] = [
NodeTransformer.ObjectExpressionKeysTransformer,
NodeTransformer.TemplateLiteralTransformer
];

/**
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
Expand Down Expand Up @@ -59,7 +68,7 @@ export class SplitStringTransformer extends AbstractNodeTransformer {
switch (transformationStage) {
case TransformationStage.Converting:
return {
leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
if (!this.options.splitStrings) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';

export type TNodeTransformersRelationEdge = [NodeTransformer, NodeTransformer | null];
5 changes: 5 additions & 0 deletions src/types/node-transformers/TNormalizedNodeTransformers.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TObject } from '../TObject';

import { INodeTransformer } from '../../interfaces/node-transformers/INodeTransformer';

export type TNormalizedNodeTransformers = TObject<INodeTransformer>;
5 changes: 5 additions & 0 deletions src/types/node-transformers/TTransformersRunnerData.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TNormalizedNodeTransformers } from './TNormalizedNodeTransformers';

import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';

export type TTransformersRunnerData = [TNormalizedNodeTransformers, NodeTransformer[][]];
Loading