Skip to content
Closed
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ v0.24.0
* Dynamic import and `import.meta` support. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/505
* Now usage of some browser-related options with `target: 'node'` will cause a validation error
* **CLI:** a file path will be displayed on obfuscation error. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/513
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/512
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/496
* **Internal:** switched from `awesome-typescript-loader` on `ts-loader`
Expand Down
12 changes: 6 additions & 6 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.24.0-rc.0",
"version": "0.24.0-rc.1",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ObjectExpressionTransformer } from '../../../node-transformers/converti
import { SplitStringTransformer } from '../../../node-transformers/converting-transformers/SplitStringTransformer';
import { TemplateLiteralTransformer } from '../../../node-transformers/converting-transformers/TemplateLiteralTransformer';
import { VariableDeclaratorPropertiesExtractor } from '../../../node-transformers/converting-transformers/properties-extractors/VariableDeclaratorPropertiesExtractor';
import { AssignmentPatternPropertiesExtractor } from '../../../node-transformers/converting-transformers/properties-extractors/AssignmentPatternPropertiesExtractor';

export const convertingTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// converting transformers
Expand Down Expand Up @@ -49,6 +50,10 @@ export const convertingTransformersModule: interfaces.ContainerModule = new Cont
.to(AssignmentExpressionPropertiesExtractor)
.whenTargetNamed(PropertiesExtractor.AssignmentExpressionPropertiesExtractor);

bind<IPropertiesExtractor>(ServiceIdentifiers.IPropertiesExtractor)
.to(AssignmentPatternPropertiesExtractor)
.whenTargetNamed(PropertiesExtractor.AssignmentPatternPropertiesExtractor);

bind<IPropertiesExtractor>(ServiceIdentifiers.IPropertiesExtractor)
.to(BasePropertiesExtractor)
.whenTargetNamed(PropertiesExtractor.BasePropertiesExtractor);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum PropertiesExtractor {
AssignmentExpressionPropertiesExtractor = 'AssignmentExpressionPropertiesExtractor',
AssignmentPatternPropertiesExtractor = 'AssignmentPatternPropertiesExtractor',
BasePropertiesExtractor = 'BasePropertiesExtractor',
VariableDeclaratorPropertiesExtractor = 'VariableDeclaratorPropertiesExtractor'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum PropertiesExtractorFlag {
Skip = 'skip'
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as ESTree from 'estree';

import { TPropertiesExtractorResult } from '../../../../types/node-transformers/TPropertiesExtractorResult';

export interface IPropertiesExtractor {
/**
* @param {ObjectExpression} objectExpressionNode
* @param {Node} hostNode
* @returns {Node}
* @returns {TPropertiesExtractorResult}
*/
extract (
objectExpressionNode: ESTree.ObjectExpression,
hostNode: ESTree.Node
): ESTree.Node;
): TPropertiesExtractorResult;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as ESTree from 'estree';

import { TPropertiesExtractorFactory } from '../../types/container/node-transformers/TPropertiesExtractorFactory';
import { TPropertiesExtractorResult } from '../../types/node-transformers/TPropertiesExtractorResult';

import { IOptions } from '../../interfaces/options/IOptions';
import { IPropertiesExtractor } from '../../interfaces/node-transformers/converting-transformers/properties-extractors/IPropertiesExtractor';
Expand All @@ -12,18 +13,25 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';

import { NodeType } from '../../enums/node/NodeType';
import { PropertiesExtractor } from '../../enums/node-transformers/converting-transformers/properties-extractors/PropertiesExtractor';
import { PropertiesExtractorFlag } from '../../enums/node-transformers/converting-transformers/properties-extractors/PropertiesExtractorResult';
import { TransformationStage } from '../../enums/node-transformers/TransformationStage';

import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';

@injectable()
export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
/**
* @type {Set<ESTree.Node>}
*/
private static readonly objectExpressionNodesToSkipSet: Set<ESTree.Node> = new Set();

/**
* @type {Map<string, PropertiesExtractor>}
*/
private static readonly propertiesExtractorsMap: Map <string, PropertiesExtractor> = new Map([
[NodeType.AssignmentExpression, PropertiesExtractor.AssignmentExpressionPropertiesExtractor],
[NodeType.AssignmentPattern, PropertiesExtractor.AssignmentPatternPropertiesExtractor],
[NodeType.VariableDeclarator, PropertiesExtractor.VariableDeclaratorPropertiesExtractor]
]);

Expand Down Expand Up @@ -110,9 +118,7 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
return objectExpressionNode;
}

const propertiesExtractor: IPropertiesExtractor = this.propertiesExtractorFactory(propertiesExtractorName);

return propertiesExtractor.extract(objectExpressionNode, parentNode);
return this.transformNodeWithExtractor(objectExpressionNode, parentNode, propertiesExtractorName);
}

/**
Expand All @@ -137,8 +143,36 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
return objectExpressionNode;
}

const propertiesExtractor: IPropertiesExtractor = this.propertiesExtractorFactory(PropertiesExtractor.BasePropertiesExtractor);
if (ObjectExpressionKeysTransformer.objectExpressionNodesToSkipSet.has(objectExpressionNode)) {
return objectExpressionNode;
}

return this.transformNodeWithExtractor(objectExpressionNode, parentNode, PropertiesExtractor.BasePropertiesExtractor);
}

/**
* @param {ObjectExpression} objectExpressionNode
* @param {Node} parentNode
* @param {PropertiesExtractor} propertiesExtractorName
* @returns {Node}
*/
private transformNodeWithExtractor (
objectExpressionNode: ESTree.ObjectExpression,
parentNode: ESTree.Node,
propertiesExtractorName: PropertiesExtractor
): ESTree.Node {
const propertiesExtractor: IPropertiesExtractor = this.propertiesExtractorFactory(propertiesExtractorName);
const extractedResult: TPropertiesExtractorResult =
propertiesExtractor.extract(objectExpressionNode, parentNode);

switch (extractedResult) {
case PropertiesExtractorFlag.Skip:
ObjectExpressionKeysTransformer.objectExpressionNodesToSkipSet.add(objectExpressionNode);

return propertiesExtractor.extract(objectExpressionNode, parentNode);
return objectExpressionNode;

default:
return extractedResult;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';

import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
import { TPropertiesExtractorResult } from '../../../types/node-transformers/TPropertiesExtractorResult';

import { IOptions } from '../../../interfaces/options/IOptions';
import { IPropertiesExtractor } from '../../../interfaces/node-transformers/converting-transformers/properties-extractors/IPropertiesExtractor';
Expand Down Expand Up @@ -88,15 +89,59 @@ export abstract class AbstractPropertiesExtractor implements IPropertiesExtracto
|| NodeGuards.isRestElementNode(node);
}

/**
* @param {ObjectExpression} objectExpressionNode
* @param {Statement} hostStatement
* @returns {boolean}
*/
protected static isProhibitedHostStatement (
objectExpressionNode: ESTree.ObjectExpression,
hostStatement: ESTree.Statement
): boolean {
if (AbstractPropertiesExtractor.isProhibitedVariableDeclarationHostStatement(objectExpressionNode, hostStatement)) {
return true;
}

return false;
}

/**
* Fix of https://github.com/javascript-obfuscator/javascript-obfuscator/issues/516
* If object expression is placed inside any expression inside variable declaration with 2+ declarators
* - should mark host node as prohibited
*
* @param {ObjectExpression} objectExpressionNode
* @param {Statement} hostStatement
* @returns {boolean}
*/
protected static isProhibitedVariableDeclarationHostStatement (
objectExpressionNode: ESTree.ObjectExpression,
hostStatement: ESTree.Statement
): boolean {
if (!NodeGuards.isVariableDeclarationNode(hostStatement)) {
return false;
}

if (objectExpressionNode.parentNode && NodeGuards.isVariableDeclaratorNode(objectExpressionNode.parentNode)) {
return false;
}

if (hostStatement.declarations.length <= 1) {
return false;
}

return true;
}

/**
* @param {ObjectExpression} objectExpressionNode
* @param {Node} hostNode
* @returns {Node}
* @returns {TPropertiesExtractorResult}
*/
public abstract extract (
objectExpressionNode: ESTree.ObjectExpression,
hostNode: ESTree.Node
): ESTree.Node;
): TPropertiesExtractorResult;

/**
* @param {Property[]} properties
Expand Down Expand Up @@ -181,11 +226,16 @@ export abstract class AbstractPropertiesExtractor implements IPropertiesExtracto
objectExpressionNode: ESTree.ObjectExpression,
memberExpressionHostNode: ESTree.Expression
): ESTree.Node {
const hostStatement: ESTree.Statement = this.getHostStatement(objectExpressionNode);

if (AbstractPropertiesExtractor.isProhibitedHostStatement(objectExpressionNode, hostStatement)) {
return objectExpressionNode;
}

const properties: ESTree.Property[] = objectExpressionNode.properties;
const [expressionStatements, removablePropertyIds]: [ESTree.ExpressionStatement[], number[]] = this
.extractPropertiesToExpressionStatements(properties, memberExpressionHostNode);

const hostStatement: ESTree.Statement = this.getHostStatement(objectExpressionNode);
const hostNodeWithStatements: TNodeWithStatements = this.getHostNodeWithStatements(
objectExpressionNode,
hostStatement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';

import * as ESTree from 'estree';

import { TPropertiesExtractorResult } from '../../../types/node-transformers/TPropertiesExtractorResult';

import { IOptions } from '../../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';

Expand Down Expand Up @@ -54,12 +56,12 @@ export class AssignmentExpressionPropertiesExtractor extends AbstractPropertiesE
/**
* @param {ObjectExpression} objectExpressionNode
* @param {AssignmentExpression} hostNode
* @returns {Node}
* @returns {TPropertiesExtractorResult}
*/
public extract (
objectExpressionNode: ESTree.ObjectExpression,
hostNode: ESTree.AssignmentExpression
): ESTree.Node {
): TPropertiesExtractorResult {
const hostParentNode: ESTree.Node | undefined = hostNode.parentNode;
const leftNode: ESTree.MemberExpression | ESTree.Pattern = hostNode.left;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';

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

import { TObjectExpressionKeysTransformerCustomNodeFactory } from '../../../types/container/custom-nodes/TObjectExpressionKeysTransformerCustomNodeFactory';
import { TPropertiesExtractorResult } from '../../../types/node-transformers/TPropertiesExtractorResult';

import { IOptions } from '../../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';

import { PropertiesExtractorFlag } from '../../../enums/node-transformers/converting-transformers/properties-extractors/PropertiesExtractorResult';

import { AbstractPropertiesExtractor } from './AbstractPropertiesExtractor';
import { BasePropertiesExtractor } from './BasePropertiesExtractor';
import { NodeGuards } from '../../../node/NodeGuards';

@injectable()
export class AssignmentPatternPropertiesExtractor extends BasePropertiesExtractor {
/**
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {TObjectExpressionKeysTransformerCustomNodeFactory} objectExpressionKeysTransformerCustomNodeFactory
*/
constructor (
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.Factory__IObjectExpressionKeysTransformerCustomNode)
objectExpressionKeysTransformerCustomNodeFactory: TObjectExpressionKeysTransformerCustomNodeFactory,
) {
super(randomGenerator, options, objectExpressionKeysTransformerCustomNodeFactory);
}

/**
* @param {AssignmentPattern} hostNode
* @returns {boolean}
*/
private static isProhibitedHostParent (hostNode: ESTree.AssignmentPattern): boolean {
const hostParentNode: ESTree.Node | undefined = hostNode.parentNode;

if (!hostParentNode) {
return true;
}

if (NodeGuards.isFunctionNode(hostParentNode)) {
return AssignmentPatternPropertiesExtractor.isProhibitedHostParentFunction(hostNode, hostParentNode);
}

return false;
}

/**
* @param {AssignmentExpression} hostNode
* @param {Function} hostParentNode
* @returns {boolean}
*/
private static isProhibitedHostParentFunction (
hostNode: ESTree.AssignmentPattern,
hostParentNode: ESTree.Function
): boolean {
const { params } = hostParentNode;
const indexOfParameter: number = params.indexOf(hostNode);
const isFirstParameter: boolean = indexOfParameter === 0;

const parametersBeforeCurrentParameter: ESTree.Pattern[] = params.slice(0, indexOfParameter + 1);
const parametersIdentifierNamesSet: Set<string> = new Set();

let isProhibitedNode: boolean = false;

// should mark node as prohibited if identifier of node using inside previous function parameters
for (const parameter of parametersBeforeCurrentParameter) {
estraverse.traverse(parameter, {
enter: (node: ESTree.Node): void | estraverse.VisitorOption => {
if (!NodeGuards.isIdentifierNode(node)) {
return;
}

if (!isFirstParameter && parametersIdentifierNamesSet.has(node.name)) {
isProhibitedNode = true;

return estraverse.VisitorOption.Break;
}

parametersIdentifierNamesSet.add(node.name);
}
});

if (isProhibitedNode) {
break;
}
}

return isProhibitedNode;
}

/**
* @param {ObjectExpression} objectExpressionNode
* @param {AssignmentPattern} hostNode
* @returns {TPropertiesExtractorResult}
*/
public extract (
objectExpressionNode: ESTree.ObjectExpression,
hostNode: ESTree.AssignmentPattern
): TPropertiesExtractorResult {
const leftNode: ESTree.Pattern = hostNode.left;

// left node shouldn't be as Pattern node
if (AbstractPropertiesExtractor.isProhibitedPattern(leftNode)) {
return objectExpressionNode;
}

// left node shouldn't be as prohibited node
if (AssignmentPatternPropertiesExtractor.isProhibitedHostParent(hostNode)) {
return PropertiesExtractorFlag.Skip;
}

return this.transformObjectExpressionNode(
objectExpressionNode,
leftNode
);
}
}
Loading