mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
forceTransformedStrings option
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
Change Log
|
||||
|
||||
v2.4.0
|
||||
---
|
||||
* **New option:** `forceTransformedStrings` allows force transform strings even if by `stringArrayThreshold` (or possible other thresholds in the future) they shouldn't be transformed
|
||||
|
||||
v2.3.1
|
||||
---
|
||||
* Fixed a rare bug with `identifierNamesGenerator: 'mangled'` option that causes wrong identifier names generation
|
||||
|
||||
@@ -339,6 +339,7 @@ Following options are available for the JS Obfuscator:
|
||||
debugProtectionInterval: false,
|
||||
disableConsoleOutput: false,
|
||||
domainLock: [],
|
||||
forceTransformedStrings: [],
|
||||
identifierNamesGenerator: 'hexadecimal',
|
||||
identifiersDictionary: [],
|
||||
identifiersPrefix: '',
|
||||
@@ -391,6 +392,7 @@ Following options are available for the JS Obfuscator:
|
||||
--disable-console-output <boolean>
|
||||
--domain-lock '<list>' (comma separated)
|
||||
--exclude '<list>' (comma separated)
|
||||
--force-transformed-strings '<list>' (comma separated)
|
||||
--identifier-names-generator <string> [dictionary, hexadecimal, mangled, mangled-shuffled]
|
||||
--identifiers-dictionary '<list>' (comma separated)
|
||||
--identifiers-prefix <string>
|
||||
@@ -656,6 +658,23 @@ Type: `string[]` Default: `[]`
|
||||
|
||||
A file names or globs which indicates files to exclude from obfuscation.
|
||||
|
||||
### `forceTransformedStrings`
|
||||
Type: `string[]` Default: `[]`
|
||||
|
||||
Enables force transformation of string literals, which being matched by passed RegExp patterns.
|
||||
|
||||
##### :warning: This option affects only strings that shouldn't be transformed by [`stringArrayThreshold`](#stringArrayThreshold) (or possible other thresholds in the future)
|
||||
|
||||
Example:
|
||||
```ts
|
||||
{
|
||||
forceTransformedStrings: [
|
||||
'some-important-value',
|
||||
'some-string_\d'
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `identifierNamesGenerator`
|
||||
Type: `string` Default: `hexadecimal`
|
||||
|
||||
|
||||
Vendored
+7
-7
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "javascript-obfuscator",
|
||||
"version": "2.3.1",
|
||||
"version": "2.4.0",
|
||||
"description": "JavaScript obfuscator",
|
||||
"keywords": [
|
||||
"obfuscator",
|
||||
|
||||
@@ -11,8 +11,8 @@ import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-a
|
||||
import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-transformers/IStringArrayStorageItem';
|
||||
|
||||
import { NodeGuards } from '../../node/NodeGuards';
|
||||
import { NodeMetadata } from '../../node/NodeMetadata';
|
||||
import { NodeLiteralUtils } from '../../node/NodeLiteralUtils';
|
||||
import { NodeMetadata } from '../../node/NodeMetadata';
|
||||
|
||||
/**
|
||||
* Adds values of literal nodes to the string array storage
|
||||
@@ -99,7 +99,7 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
|
||||
* @param {Node} parentNode
|
||||
*/
|
||||
private analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
|
||||
if (typeof literalNode.value !== 'string') {
|
||||
if (!NodeLiteralUtils.isStringLiteralNode(literalNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.shouldAddValueToStringArray(literalNode.value)) {
|
||||
if (!this.shouldAddValueToStringArray(literalNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,11 +118,17 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @param {(SimpleLiteral & {value: string})} literalNode
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private shouldAddValueToStringArray (value: string): boolean {
|
||||
return value.length >= StringArrayStorageAnalyzer.minimumLengthForStringArray
|
||||
private shouldAddValueToStringArray (literalNode: ESTree.Literal & {value: string}): boolean {
|
||||
const isForceObfuscatedNode: boolean = NodeMetadata.isForceObfuscatedNode(literalNode);
|
||||
|
||||
if (isForceObfuscatedNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return literalNode.value.length >= StringArrayStorageAnalyzer.minimumLengthForStringArray
|
||||
&& this.randomGenerator.getMathRandom() <= this.options.stringArrayThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +230,11 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
'A filename or glob which indicates files to exclude from obfuscation',
|
||||
ArraySanitizer
|
||||
)
|
||||
.option(
|
||||
'--force-transformed-strings <list> (comma separated, without whitespaces)',
|
||||
'Enables force transformation of string literals, which being matched by passed RegExp patterns (comma separated)',
|
||||
ArraySanitizer
|
||||
)
|
||||
.option(
|
||||
'--identifier-names-generator <string>',
|
||||
'Sets identifier names generator. ' +
|
||||
|
||||
@@ -12,6 +12,7 @@ import { BlackListObfuscatingGuard } from '../../../node-transformers/preparing-
|
||||
import { ConditionalCommentObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ConditionalCommentObfuscatingGuard';
|
||||
import { CustomCodeHelpersTransformer } from '../../../node-transformers/preparing-transformers/CustomCodeHelpersTransformer';
|
||||
import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvalCallExpressionTransformer';
|
||||
import { ForceTransformedStringObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ForceTransformedStringObfuscatingGuard';
|
||||
import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer';
|
||||
import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer';
|
||||
import { ParentificationTransformer } from '../../../node-transformers/preparing-transformers/ParentificationTransformer';
|
||||
@@ -40,6 +41,10 @@ export const preparingTransformersModule: interfaces.ContainerModule = new Conta
|
||||
.to(ParentificationTransformer)
|
||||
.whenTargetNamed(NodeTransformer.ParentificationTransformer);
|
||||
|
||||
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
|
||||
.to(VariablePreserveTransformer)
|
||||
.whenTargetNamed(NodeTransformer.VariablePreserveTransformer);
|
||||
|
||||
// obfuscating guards
|
||||
bind<IObfuscatingGuard>(ServiceIdentifiers.INodeGuard)
|
||||
.to(BlackListObfuscatingGuard)
|
||||
@@ -51,15 +56,16 @@ export const preparingTransformersModule: interfaces.ContainerModule = new Conta
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(ObfuscatingGuard.ConditionalCommentObfuscatingGuard);
|
||||
|
||||
bind<IObfuscatingGuard>(ServiceIdentifiers.INodeGuard)
|
||||
.to(ForceTransformedStringObfuscatingGuard)
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(ObfuscatingGuard.ForceTransformedStringObfuscatingGuard);
|
||||
|
||||
bind<IObfuscatingGuard>(ServiceIdentifiers.INodeGuard)
|
||||
.to(ReservedStringObfuscatingGuard)
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(ObfuscatingGuard.ReservedStringObfuscatingGuard);
|
||||
|
||||
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
|
||||
.to(VariablePreserveTransformer)
|
||||
.whenTargetNamed(NodeTransformer.VariablePreserveTransformer);
|
||||
|
||||
// obfuscating guards factory
|
||||
bind<IObfuscatingGuard>(ServiceIdentifiers.Factory__INodeGuard)
|
||||
.toFactory<IObfuscatingGuard>(InversifyContainerFacade
|
||||
|
||||
Vendored
+1
@@ -6,6 +6,7 @@ import * as eslintScope from 'eslint-scope';
|
||||
|
||||
declare module 'estree' {
|
||||
export interface BaseNodeMetadata {
|
||||
forceObfuscatedNode?: boolean;
|
||||
ignoredNode?: boolean;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
export enum ObfuscatingGuard {
|
||||
BlackListObfuscatingGuard = 'BlackListObfuscatingGuard',
|
||||
ConditionalCommentObfuscatingGuard = 'ConditionalCommentObfuscatingGuard',
|
||||
ForceTransformedStringObfuscatingGuard = 'ForceTransformedStringObfuscatingGuard',
|
||||
ReservedStringObfuscatingGuard = 'ReservedStringObfuscatingGuard'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum ObfuscatingGuardResult {
|
||||
ForceObfuscated = 'ForceObfuscated',
|
||||
Ignored = 'Ignored',
|
||||
Obfuscated = 'Obfuscated'
|
||||
}
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { TNodeGuard } from '../../../../types/node/TNodeGuard';
|
||||
import { TObfuscatingGuard } from '../../../../types/node/TObfuscatingGuard';
|
||||
|
||||
export interface IObfuscatingGuard {
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
check: TNodeGuard;
|
||||
check: TObfuscatingGuard;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface IOptions {
|
||||
readonly debugProtectionInterval: boolean;
|
||||
readonly disableConsoleOutput: boolean;
|
||||
readonly domainLock: string[];
|
||||
readonly forceTransformedStrings: string[];
|
||||
readonly identifierNamesGenerator: TypeFromEnum<typeof IdentifierNamesGenerator>;
|
||||
readonly identifiersDictionary: string[];
|
||||
readonly identifiersPrefix: string;
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCu
|
||||
|
||||
import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
|
||||
import { NodeGuards } from '../../../node/NodeGuards';
|
||||
import { NodeLiteralUtils } from '../../../node/NodeLiteralUtils';
|
||||
import { StringLiteralControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode';
|
||||
import { StringLiteralNode } from '../../../custom-nodes/control-flow-flattening-nodes/StringLiteralNode';
|
||||
|
||||
@@ -55,7 +56,7 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
if (typeof literalNode.value !== 'string' || literalNode.value.length < 3) {
|
||||
if (!NodeLiteralUtils.isStringLiteralNode(literalNode) || literalNode.value.length < 3) {
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ export class SplitStringTransformer extends AbstractNodeTransformer {
|
||||
parentNode: ESTree.Node,
|
||||
chunkLength: number
|
||||
): ESTree.Node {
|
||||
if (typeof literalNode.value !== 'string') {
|
||||
if (!NodeLiteralUtils.isStringLiteralNode(literalNode)) {
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
||||
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
|
||||
|
||||
import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
|
||||
import { ObfuscatingGuard } from '../../enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard';
|
||||
import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
|
||||
import { ObfuscatingGuard } from '../../enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard';
|
||||
import { ObfuscatingGuardResult } from '../../enums/node/ObfuscatingGuardResult';
|
||||
|
||||
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
|
||||
import { NodeGuards } from '../../node/NodeGuards';
|
||||
@@ -29,6 +30,7 @@ export class ObfuscatingGuardsTransformer extends AbstractNodeTransformer {
|
||||
private static readonly obfuscatingGuardsList: ObfuscatingGuard[] = [
|
||||
ObfuscatingGuard.BlackListObfuscatingGuard,
|
||||
ObfuscatingGuard.ConditionalCommentObfuscatingGuard,
|
||||
ObfuscatingGuard.ForceTransformedStringObfuscatingGuard,
|
||||
ObfuscatingGuard.ReservedStringObfuscatingGuard
|
||||
];
|
||||
|
||||
@@ -84,13 +86,37 @@ export class ObfuscatingGuardsTransformer extends AbstractNodeTransformer {
|
||||
* @returns {Node}
|
||||
*/
|
||||
public transformNode (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node {
|
||||
const obfuscationAllowed: boolean = this.obfuscatingGuards
|
||||
.every((nodeGuard: IObfuscatingGuard) => nodeGuard.check(node));
|
||||
const obfuscatingGuardResults: ObfuscatingGuardResult[] = this.obfuscatingGuards
|
||||
.map((obfuscatingGuard: IObfuscatingGuard) => obfuscatingGuard.check(node));
|
||||
|
||||
NodeMetadata.set(node, {
|
||||
ignoredNode: !(NodeGuards.isProgramNode(node) || obfuscationAllowed)
|
||||
});
|
||||
this.setNodeMetadata(node, obfuscatingGuardResults);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @param {ObfuscatingGuardResult[]} obfuscatingGuardResults
|
||||
*/
|
||||
private setNodeMetadata (node: ESTree.Node, obfuscatingGuardResults: ObfuscatingGuardResult[]): void {
|
||||
let ignoredNode: boolean = false;
|
||||
let forceObfuscatedNode: boolean = false;
|
||||
|
||||
for (const obfuscatingGuardResult of obfuscatingGuardResults) {
|
||||
if (obfuscatingGuardResult === ObfuscatingGuardResult.Ignored) {
|
||||
ignoredNode = true;
|
||||
forceObfuscatedNode = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (obfuscatingGuardResult === ObfuscatingGuardResult.ForceObfuscated) {
|
||||
forceObfuscatedNode = true;
|
||||
}
|
||||
}
|
||||
|
||||
NodeMetadata.set(node, {
|
||||
ignoredNode: ignoredNode && !NodeGuards.isProgramNode(node),
|
||||
forceObfuscatedNode: forceObfuscatedNode && !NodeGuards.isProgramNode(node)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -2,10 +2,10 @@ import { injectable } from 'inversify';
|
||||
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TNodeGuard } from '../../../types/node/TNodeGuard';
|
||||
|
||||
import { IObfuscatingGuard } from '../../../interfaces/node-transformers/preparing-transformers/obfuscating-guards/IObfuscatingGuard';
|
||||
|
||||
import { ObfuscatingGuardResult } from '../../../enums/node/ObfuscatingGuardResult';
|
||||
|
||||
import { NodeGuards } from '../../../node/NodeGuards';
|
||||
|
||||
@injectable()
|
||||
@@ -13,7 +13,7 @@ export class BlackListObfuscatingGuard implements IObfuscatingGuard {
|
||||
/**
|
||||
* @type {((node: Node) => boolean)[]}
|
||||
*/
|
||||
private static readonly blackListGuards: TNodeGuard[] = [
|
||||
private static readonly blackListGuards: ((node: ESTree.Node) => boolean)[] = [
|
||||
NodeGuards.isUseStrictOperator
|
||||
];
|
||||
|
||||
@@ -27,16 +27,16 @@ export class BlackListObfuscatingGuard implements IObfuscatingGuard {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @param node
|
||||
* @param {Node} node
|
||||
* @returns {ObfuscatingGuardResult}
|
||||
*/
|
||||
public check (node: ESTree.Node): boolean {
|
||||
public check (node: ESTree.Node): ObfuscatingGuardResult {
|
||||
for (let i: number = 0; i < this.blackListGuardsLength; i++) {
|
||||
if (BlackListObfuscatingGuard.blackListGuards[i](node)) {
|
||||
return false;
|
||||
return ObfuscatingGuardResult.Ignored;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return ObfuscatingGuardResult.Obfuscated;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-12
@@ -4,6 +4,8 @@ import * as ESTree from 'estree';
|
||||
|
||||
import { IObfuscatingGuard } from '../../../interfaces/node-transformers/preparing-transformers/obfuscating-guards/IObfuscatingGuard';
|
||||
|
||||
import { ObfuscatingGuardResult } from '../../../enums/node/ObfuscatingGuardResult';
|
||||
|
||||
import { NodeGuards } from '../../../node/NodeGuards';
|
||||
|
||||
@injectable()
|
||||
@@ -33,21 +35,21 @@ export class ConditionalCommentObfuscatingGuard implements IObfuscatingGuard {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @param node
|
||||
* @param {Node} node
|
||||
* @returns {ObfuscatingGuardResult}
|
||||
*/
|
||||
public check (node: ESTree.Node): boolean {
|
||||
if (!NodeGuards.isNodeWithComments(node)) {
|
||||
return this.obfuscationAllowed;
|
||||
public check (node: ESTree.Node): ObfuscatingGuardResult {
|
||||
if (NodeGuards.isNodeWithComments(node)) {
|
||||
const leadingComments: ESTree.Comment[] | undefined = node.leadingComments;
|
||||
|
||||
if (leadingComments) {
|
||||
this.obfuscationAllowed = this.checkComments(leadingComments);
|
||||
}
|
||||
}
|
||||
|
||||
const leadingComments: ESTree.Comment[] | undefined = node.leadingComments;
|
||||
|
||||
if (leadingComments) {
|
||||
this.obfuscationAllowed = this.checkComments(leadingComments);
|
||||
}
|
||||
|
||||
return this.obfuscationAllowed;
|
||||
return this.obfuscationAllowed
|
||||
? ObfuscatingGuardResult.Obfuscated
|
||||
: ObfuscatingGuardResult.Ignored;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { IObfuscatingGuard } from '../../../interfaces/node-transformers/preparing-transformers/obfuscating-guards/IObfuscatingGuard';
|
||||
import { IOptions } from '../../../interfaces/options/IOptions';
|
||||
|
||||
import { ObfuscatingGuardResult } from '../../../enums/node/ObfuscatingGuardResult';
|
||||
|
||||
import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
|
||||
|
||||
import { NodeGuards } from '../../../node/NodeGuards';
|
||||
|
||||
@injectable()
|
||||
export class ForceTransformedStringObfuscatingGuard implements IObfuscatingGuard {
|
||||
/**
|
||||
* @type {IOptions}
|
||||
*/
|
||||
private readonly options: IOptions;
|
||||
|
||||
/**
|
||||
* @param {IOptions} options
|
||||
*/
|
||||
public constructor (
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions
|
||||
) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {ObfuscatingGuardResult}
|
||||
*/
|
||||
public check (node: ESTree.Node): ObfuscatingGuardResult {
|
||||
if (
|
||||
this.options.forceTransformedStrings.length
|
||||
&& NodeGuards.isLiteralNode(node)
|
||||
&& typeof node.value === 'string'
|
||||
) {
|
||||
return !this.isForceTransformedString(node.value)
|
||||
? ObfuscatingGuardResult.Obfuscated
|
||||
: ObfuscatingGuardResult.ForceObfuscated;
|
||||
}
|
||||
|
||||
return ObfuscatingGuardResult.Obfuscated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private isForceTransformedString (value: string): boolean {
|
||||
return this.options.forceTransformedStrings
|
||||
.some((forceTransformedString: string) => {
|
||||
return new RegExp(forceTransformedString, 'g').exec(value) !== null;
|
||||
});
|
||||
}
|
||||
}
|
||||
+9
-5
@@ -5,6 +5,8 @@ import * as ESTree from 'estree';
|
||||
import { IObfuscatingGuard } from '../../../interfaces/node-transformers/preparing-transformers/obfuscating-guards/IObfuscatingGuard';
|
||||
import { IOptions } from '../../../interfaces/options/IOptions';
|
||||
|
||||
import { ObfuscatingGuardResult } from '../../../enums/node/ObfuscatingGuardResult';
|
||||
|
||||
import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
|
||||
|
||||
import { NodeGuards } from '../../../node/NodeGuards';
|
||||
@@ -26,19 +28,21 @@ export class ReservedStringObfuscatingGuard implements IObfuscatingGuard {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @param node
|
||||
* @param {Node} node
|
||||
* @returns {ObfuscatingGuardResult}
|
||||
*/
|
||||
public check (node: ESTree.Node): boolean {
|
||||
public check (node: ESTree.Node): ObfuscatingGuardResult {
|
||||
if (
|
||||
this.options.reservedStrings.length
|
||||
&& NodeGuards.isLiteralNode(node)
|
||||
&& typeof node.value === 'string'
|
||||
) {
|
||||
return !this.isReservedString(node.value);
|
||||
return !this.isReservedString(node.value)
|
||||
? ObfuscatingGuardResult.Obfuscated
|
||||
: ObfuscatingGuardResult.Ignored;
|
||||
}
|
||||
|
||||
return true;
|
||||
return ObfuscatingGuardResult.Obfuscated;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -191,7 +191,10 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
|
||||
* @returns {NodeGuards}
|
||||
*/
|
||||
public transformNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): ESTree.Node {
|
||||
if (typeof literalNode.value !== 'string' || NodeLiteralUtils.isProhibitedLiteralNode(literalNode, parentNode)) {
|
||||
if (
|
||||
!NodeLiteralUtils.isStringLiteralNode(literalNode)
|
||||
|| NodeLiteralUtils.isProhibitedLiteralNode(literalNode, parentNode)
|
||||
) {
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
@@ -413,7 +416,7 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
|
||||
literalNode: ESTree.Literal,
|
||||
parentNode: ESTree.Node
|
||||
): ESTree.Literal {
|
||||
if (typeof literalNode.value !== 'string') {
|
||||
if (!NodeLiteralUtils.isStringLiteralNode(literalNode)) {
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,14 @@ import * as ESTree from 'estree';
|
||||
import { NodeGuards } from './NodeGuards';
|
||||
|
||||
export class NodeLiteralUtils {
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @returns {literalNode is (SimpleLiteral & {value: string})}
|
||||
*/
|
||||
public static isStringLiteralNode (literalNode: ESTree.Literal): literalNode is ESTree.Literal & {value: string} {
|
||||
return typeof literalNode.value === 'string';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @param {Node} parentNode
|
||||
|
||||
@@ -20,6 +20,14 @@ export class NodeMetadata {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isForceObfuscatedNode (node: ESTree.Node): boolean {
|
||||
return NodeMetadata.get(node, 'forceObfuscatedNode') === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
|
||||
@@ -128,6 +128,16 @@ export class Options implements IOptions {
|
||||
])
|
||||
public readonly domainLock!: string[];
|
||||
|
||||
/**
|
||||
* @type {string[]}
|
||||
*/
|
||||
@IsArray()
|
||||
@ArrayUnique()
|
||||
@IsString({
|
||||
each: true
|
||||
})
|
||||
public readonly forceTransformedStrings!: string[];
|
||||
|
||||
/**
|
||||
* @type {IdentifierNamesGenerator}
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,6 @@ import { SourceMapFileNameRule } from './normalizer-rules/SourceMapFileNameRule'
|
||||
import { SplitStringsChunkLengthRule } from './normalizer-rules/SplitStringsChunkLengthRule';
|
||||
import { StringArrayRule } from './normalizer-rules/StringArrayRule';
|
||||
import { StringArrayEncodingRule } from './normalizer-rules/StringArrayEncodingRule';
|
||||
import { StringArrayThresholdRule } from './normalizer-rules/StringArrayThresholdRule';
|
||||
import { StringArrayWrappersChainedCallsRule } from './normalizer-rules/StringArrayWappersChainedCalls';
|
||||
|
||||
@injectable()
|
||||
@@ -38,7 +37,6 @@ export class OptionsNormalizer implements IOptionsNormalizer {
|
||||
SplitStringsChunkLengthRule,
|
||||
StringArrayRule,
|
||||
StringArrayEncodingRule,
|
||||
StringArrayThresholdRule,
|
||||
StringArrayWrappersChainedCallsRule,
|
||||
];
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { TOptionsNormalizerRule } from '../../types/options/TOptionsNormalizerRule';
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
|
||||
import { StringArrayEncoding } from '../../enums/node-transformers/string-array-transformers/StringArrayEncoding';
|
||||
|
||||
/**
|
||||
* @param {IOptions} options
|
||||
* @returns {IOptions}
|
||||
*/
|
||||
export const StringArrayThresholdRule: TOptionsNormalizerRule = (options: IOptions): IOptions => {
|
||||
if (options.stringArrayThreshold === 0) {
|
||||
options = {
|
||||
...options,
|
||||
rotateStringArray: false,
|
||||
stringArray: false,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
],
|
||||
stringArrayWrappersChainedCalls: false,
|
||||
stringArrayWrappersCount: 0,
|
||||
stringArrayThreshold: 0
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
@@ -19,6 +19,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
|
||||
disableConsoleOutput: false,
|
||||
domainLock: [],
|
||||
exclude: [],
|
||||
forceTransformedStrings: [],
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
identifiersPrefix: '',
|
||||
identifiersDictionary: [],
|
||||
|
||||
@@ -17,6 +17,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
|
||||
disableConsoleOutput: false,
|
||||
domainLock: [],
|
||||
exclude: [],
|
||||
forceTransformedStrings: [],
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
identifiersPrefix: '',
|
||||
identifiersDictionary: [],
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
export type TNodeGuard = (node: ESTree.Node) => boolean;
|
||||
@@ -0,0 +1,5 @@
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { ObfuscatingGuardResult } from '../../enums/node/ObfuscatingGuardResult';
|
||||
|
||||
export type TObfuscatingGuard = (node: ESTree.Node) => ObfuscatingGuardResult;
|
||||
+2
-1
@@ -18,9 +18,10 @@ import { StringArrayWrappersType } from '../../src/enums/node-transformers/strin
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
compact: false,
|
||||
forceTransformedStrings: ['foo'],
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayThreshold: 0,
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 1,
|
||||
stringArrayWrappersType: StringArrayWrappersType.Function
|
||||
|
||||
+185
-4
@@ -689,7 +689,188 @@ describe('StringArrayTransformer', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #16: object expression key literal', () => {
|
||||
describe('Variant #16: `forceTransformedStrings` option is enabled', () => {
|
||||
describe('Variant #1: base `forceTransformedStrings` values', () => {
|
||||
describe('Variant #1: single force transformed string value', () => {
|
||||
const stringLiteralRegExp1: RegExp = /const foo *= *'foo';/;
|
||||
const stringLiteralRegExp2: RegExp = /const bar *= *_0x([a-f0-9]){4}\('0x0'\);/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/force-transformed-strings-option-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
forceTransformedStrings: ['bar'],
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 0
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should not transform string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp1);
|
||||
});
|
||||
|
||||
it('match #2: should transform force transformed string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: two force transformed string values', () => {
|
||||
const stringLiteralRegExp1: RegExp = /const foo *= *_0x([a-f0-9]){4}\('0x0'\);/;
|
||||
const stringLiteralRegExp2: RegExp = /const bar *= *_0x([a-f0-9]){4}\('0x1'\);/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/force-transformed-strings-option-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
forceTransformedStrings: ['foo', 'bar'],
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 0
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should transform force transformed string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp1);
|
||||
});
|
||||
|
||||
it('match #2: should transform force transformed string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: RegExp `forceTransformedStrings` values', () => {
|
||||
describe('Variant #1: single force transformed string value', () => {
|
||||
const stringLiteralRegExp1: RegExp = /const foo *= *'foo'/;
|
||||
const stringLiteralRegExp2: RegExp = /const bar *= *_0x([a-f0-9]){4}\('0x0'\);/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/force-transformed-strings-option-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
forceTransformedStrings: ['ar$'],
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 0
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should not transform string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp1);
|
||||
});
|
||||
|
||||
it('match #2: should transform force transformed string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: two force transformed string values', () => {
|
||||
const stringLiteralRegExp1: RegExp = /const foo *= *_0x([a-f0-9]){4}\('0x0'\);/;
|
||||
const stringLiteralRegExp2: RegExp = /const bar *= *_0x([a-f0-9]){4}\('0x1'\);/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/force-transformed-strings-option-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
forceTransformedStrings: ['^fo', '.ar'],
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should transform force transformed string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp1);
|
||||
});
|
||||
|
||||
it('match #2: should transform force transformed string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: `unicodeEscapeSequence` option is disabled', () => {
|
||||
const stringLiteralRegExp1: RegExp = /const foo *= *'foo';/;
|
||||
const stringLiteralRegExp2: RegExp = /const bar *= *'bar';/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/force-transformed-strings-option-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
forceTransformedStrings: ['bar'],
|
||||
unicodeEscapeSequence: false
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should not encode force transformed string with unicode escape sequence', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp1);
|
||||
});
|
||||
|
||||
it('match #2: should not encode force transformed string with unicode escape sequence', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: `stringArray` option is disabled', () => {
|
||||
describe('Variant #1: base case', () => {
|
||||
const stringLiteralRegExp1: RegExp = /const foo *= *'foo';/;
|
||||
const stringLiteralRegExp2: RegExp = /const bar *= *'bar';/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/force-transformed-strings-option-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
forceTransformedStrings: ['foo', 'bar'],
|
||||
stringArray: false,
|
||||
stringArrayThreshold: 0
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should not transform string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp1);
|
||||
});
|
||||
|
||||
it('match #2: should not transform string', () => {
|
||||
assert.match(obfuscatedCode, stringLiteralRegExp2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #17: object expression key literal', () => {
|
||||
describe('Variant #1: base key literal', () => {
|
||||
const stringArrayRegExp: RegExp = /^var _0x([a-f0-9]){4} *= *\['bar'];/;
|
||||
const objectExpressionRegExp: RegExp = /var test *= *{'foo' *: *_0x([a-f0-9]){4}\('0x0'\)};/;
|
||||
@@ -747,7 +928,7 @@ describe('StringArrayTransformer', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #17: import declaration source literal', () => {
|
||||
describe('Variant #18: import declaration source literal', () => {
|
||||
const importDeclarationRegExp: RegExp = /import *{ *bar *} *from *'foo';/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
@@ -770,7 +951,7 @@ describe('StringArrayTransformer', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #18: export all declaration source literal', () => {
|
||||
describe('Variant #19: export all declaration source literal', () => {
|
||||
const exportAllDeclarationRegExp: RegExp = /export *\* *from *'foo';/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
@@ -793,7 +974,7 @@ describe('StringArrayTransformer', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #19: export named declaration source literal', () => {
|
||||
describe('Variant #20: export named declaration source literal', () => {
|
||||
const exportNamedDeclarationRegExp: RegExp = /export *{ *bar *} *from *'foo';/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
const foo = 'foo';
|
||||
const bar = 'bar';
|
||||
@@ -587,34 +587,6 @@ describe('OptionsNormalizer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('stringArrayThresholdRule', () => {
|
||||
before(() => {
|
||||
optionsPreset = getNormalizedOptions({
|
||||
...getDefaultOptions(),
|
||||
rotateStringArray: true,
|
||||
shuffleStringArray: true,
|
||||
stringArray: true,
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 5,
|
||||
stringArrayThreshold: 0
|
||||
});
|
||||
|
||||
expectedOptionsPreset = {
|
||||
...getDefaultOptions(),
|
||||
rotateStringArray: false,
|
||||
shuffleStringArray: false,
|
||||
stringArray: false,
|
||||
stringArrayWrappersChainedCalls: false,
|
||||
stringArrayWrappersCount: 0,
|
||||
stringArrayThreshold: 0
|
||||
};
|
||||
});
|
||||
|
||||
it('should normalize options preset', () => {
|
||||
assert.deepEqual(optionsPreset, expectedOptionsPreset);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stringArrayWrappersChainedCallsRule', () => {
|
||||
before(() => {
|
||||
optionsPreset = getNormalizedOptions({
|
||||
|
||||
+85
-1
@@ -213,7 +213,7 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Analyzes of the AST tree with ignored nodes', () => {
|
||||
describe('Analyzes of the AST tree with ignored string literal nodes', () => {
|
||||
const literalNode1: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
const literalNode2: ESTree.Literal = NodeFactory.literalNode('bar');
|
||||
NodeMetadata.set(literalNode2, {ignoredNode: true});
|
||||
@@ -254,6 +254,90 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Analyzes of the AST tree with force obfuscated string literal nodes', () => {
|
||||
describe('Variant #1: Force obfuscate string when threshold is `0`', () => {
|
||||
const literalNode1: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
const literalNode2: ESTree.Literal = NodeFactory.literalNode('bar');
|
||||
NodeMetadata.set(literalNode2, {forceObfuscatedNode: true});
|
||||
|
||||
const expectedStringArrayStorageItemData1: undefined = undefined;
|
||||
const expectedStringArrayStorageItemData2: IStringArrayStorageItemData = {
|
||||
encodedValue: 'bar',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'bar'
|
||||
};
|
||||
|
||||
let stringArrayStorageItemData1: IStringArrayStorageItemData | undefined;
|
||||
let stringArrayStorageItemData2: IStringArrayStorageItemData | undefined;
|
||||
|
||||
before(() => {
|
||||
stringArrayStorageAnalyzer = getStringArrayStorageAnalyzer({
|
||||
stringArrayThreshold: 0
|
||||
});
|
||||
|
||||
const astTree: ESTree.Program = NodeFactory.programNode([
|
||||
NodeFactory.expressionStatementNode(literalNode1),
|
||||
NodeFactory.expressionStatementNode(literalNode2)
|
||||
]);
|
||||
|
||||
stringArrayStorageAnalyzer.analyze(astTree);
|
||||
stringArrayStorageItemData1 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode1);
|
||||
stringArrayStorageItemData2 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode2);
|
||||
});
|
||||
|
||||
it('Variant #1: should return correct string array storage item data for literal node #1', () => {
|
||||
assert.deepEqual(stringArrayStorageItemData1, expectedStringArrayStorageItemData1);
|
||||
});
|
||||
|
||||
it('Variant #2: should return correct string array storage item data for literal node #1', () => {
|
||||
assert.deepEqual(stringArrayStorageItemData2, expectedStringArrayStorageItemData2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: Force obfuscate string when string value shorter than allowed length', () => {
|
||||
const literalNode1: ESTree.Literal = NodeFactory.literalNode('a');
|
||||
const literalNode2: ESTree.Literal = NodeFactory.literalNode('b');
|
||||
NodeMetadata.set(literalNode2, {forceObfuscatedNode: true});
|
||||
|
||||
const expectedStringArrayStorageItemData1: undefined = undefined;
|
||||
const expectedStringArrayStorageItemData2: IStringArrayStorageItemData = {
|
||||
encodedValue: 'b',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'b'
|
||||
};
|
||||
|
||||
let stringArrayStorageItemData1: IStringArrayStorageItemData | undefined;
|
||||
let stringArrayStorageItemData2: IStringArrayStorageItemData | undefined;
|
||||
|
||||
before(() => {
|
||||
stringArrayStorageAnalyzer = getStringArrayStorageAnalyzer({
|
||||
stringArrayThreshold: 1
|
||||
});
|
||||
|
||||
const astTree: ESTree.Program = NodeFactory.programNode([
|
||||
NodeFactory.expressionStatementNode(literalNode1),
|
||||
NodeFactory.expressionStatementNode(literalNode2)
|
||||
]);
|
||||
|
||||
stringArrayStorageAnalyzer.analyze(astTree);
|
||||
stringArrayStorageItemData1 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode1);
|
||||
stringArrayStorageItemData2 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode2);
|
||||
});
|
||||
|
||||
it('Variant #1: should return correct string array storage item data for literal node #1', () => {
|
||||
assert.deepEqual(stringArrayStorageItemData1, expectedStringArrayStorageItemData1);
|
||||
});
|
||||
|
||||
it('Variant #2: should return correct string array storage item data for literal node #1', () => {
|
||||
assert.deepEqual(stringArrayStorageItemData2, expectedStringArrayStorageItemData2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This test covers rare case when with random value inside `shouldAddValueToStringArray` was `0`
|
||||
* that trigger positive check for method.
|
||||
|
||||
+17
-16
@@ -174,6 +174,7 @@ describe('MangledIdentifierNamesGenerator', () => {
|
||||
describe('isIncrementedMangledName', function () {
|
||||
this.timeout(60000);
|
||||
|
||||
const samplesCount: number = 1000000;
|
||||
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
|
||||
|
||||
inversifyContainerFacade.load('', '', {});
|
||||
@@ -182,29 +183,29 @@ describe('MangledIdentifierNamesGenerator', () => {
|
||||
IdentifierNamesGenerator.MangledIdentifierNamesGenerator
|
||||
);
|
||||
|
||||
let isSuccessComparison: boolean = true;
|
||||
let mangledName: string = '';
|
||||
let prevMangledName: string = '9';
|
||||
|
||||
for (let sample = 0; sample <= 10000; sample++) {
|
||||
describe(`Variant #${sample + 1}`, () => {
|
||||
let resultNormal: boolean;
|
||||
let resultReversed: boolean;
|
||||
for (let sample = 0; sample <= samplesCount; sample++) {
|
||||
let resultNormal: boolean;
|
||||
let resultReversed: boolean;
|
||||
|
||||
mangledName = identifierNamesGenerator.generateNext();
|
||||
resultNormal = MangledIdentifierNamesGenerator.isIncrementedMangledName(mangledName, prevMangledName);
|
||||
resultReversed = MangledIdentifierNamesGenerator.isIncrementedMangledName(prevMangledName, mangledName);
|
||||
mangledName = identifierNamesGenerator.generateNext();
|
||||
resultNormal = MangledIdentifierNamesGenerator.isIncrementedMangledName(mangledName, prevMangledName);
|
||||
resultReversed = MangledIdentifierNamesGenerator.isIncrementedMangledName(prevMangledName, mangledName);
|
||||
|
||||
it(`Variant #1: should compare mangled names: ${mangledName}, ${prevMangledName}`, () => {
|
||||
assert.isTrue(resultNormal);
|
||||
});
|
||||
if (!resultNormal || resultReversed) {
|
||||
isSuccessComparison = false;
|
||||
break;
|
||||
}
|
||||
|
||||
it(`Variant #2: should compare mangled names: ${prevMangledName}, ${mangledName}`, () => {
|
||||
assert.isFalse(resultReversed);
|
||||
});
|
||||
|
||||
prevMangledName = mangledName;
|
||||
});
|
||||
prevMangledName = mangledName;
|
||||
}
|
||||
|
||||
it('should correctly compare mangled names', () => {
|
||||
assert.isTrue(isSuccessComparison);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isValidIdentifierName', () => {
|
||||
|
||||
+73
-6
@@ -12,23 +12,34 @@ import { INodeTransformer } from '../../../../src/interfaces/node-transformers/I
|
||||
|
||||
import { NodeTransformer } from '../../../../src/enums/node-transformers/NodeTransformer';
|
||||
import { NodeFactory } from '../../../../src/node/NodeFactory';
|
||||
import { NodeUtils } from '../../../../src/node/NodeUtils';
|
||||
import { NodeMetadata } from '../../../../src/node/NodeMetadata';
|
||||
import { NodeUtils } from '../../../../src/node/NodeUtils';
|
||||
|
||||
describe('ObfuscatingGuardsTransformer', () => {
|
||||
describe('transformNode', () => {
|
||||
const forceObfuscatedString: string = 'important string';
|
||||
const ignoredAndForceObfuscatedString: string = 'important ignored string';
|
||||
|
||||
let inversifyContainerFacade: IInversifyContainerFacade,
|
||||
obfuscatingGuardsTransformer: INodeTransformer;
|
||||
|
||||
before(() => {
|
||||
inversifyContainerFacade = new InversifyContainerFacade();
|
||||
inversifyContainerFacade.load('', '', {});
|
||||
inversifyContainerFacade.load('', '', {
|
||||
forceTransformedStrings: [
|
||||
forceObfuscatedString,
|
||||
ignoredAndForceObfuscatedString
|
||||
],
|
||||
reservedStrings: [
|
||||
ignoredAndForceObfuscatedString
|
||||
]
|
||||
});
|
||||
|
||||
obfuscatingGuardsTransformer = inversifyContainerFacade
|
||||
.getNamed(ServiceIdentifiers.INodeTransformer, NodeTransformer.ObfuscatingGuardsTransformer);
|
||||
});
|
||||
|
||||
describe('Variant #1: valid node', () => {
|
||||
describe('Variant #1: allowed node', () => {
|
||||
const identifier: ESTree.Identifier = NodeFactory.identifierNode('foo');
|
||||
|
||||
const expectedResult: ESTree.Identifier = NodeUtils.clone(identifier);
|
||||
@@ -38,7 +49,10 @@ describe('ObfuscatingGuardsTransformer', () => {
|
||||
before(() => {
|
||||
identifier.parentNode = identifier;
|
||||
|
||||
NodeMetadata.set(expectedResult, { ignoredNode: false });
|
||||
NodeMetadata.set(expectedResult, {
|
||||
forceObfuscatedNode: false,
|
||||
ignoredNode: false
|
||||
});
|
||||
|
||||
result = <ESTree.Identifier>obfuscatingGuardsTransformer.transformNode(identifier, identifier);
|
||||
});
|
||||
@@ -48,7 +62,7 @@ describe('ObfuscatingGuardsTransformer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: invalid node', () => {
|
||||
describe('Variant #2: ignored node', () => {
|
||||
const expressionStatement: ESTree.ExpressionStatement = NodeFactory.directiveNode(
|
||||
NodeFactory.literalNode('use strict'),
|
||||
'use strict'
|
||||
@@ -63,7 +77,10 @@ describe('ObfuscatingGuardsTransformer', () => {
|
||||
expressionStatement.expression.parentNode = expressionStatement;
|
||||
|
||||
expectedResult.parentNode = expectedResult;
|
||||
NodeMetadata.set(expectedResult, { ignoredNode: true });
|
||||
NodeMetadata.set(expectedResult, {
|
||||
forceObfuscatedNode: false,
|
||||
ignoredNode: true
|
||||
});
|
||||
|
||||
result = <ESTree.ExpressionStatement>obfuscatingGuardsTransformer
|
||||
.transformNode(expressionStatement, expressionStatement);
|
||||
@@ -73,5 +90,55 @@ describe('ObfuscatingGuardsTransformer', () => {
|
||||
assert.deepEqual(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: force obfuscated node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(forceObfuscatedString);
|
||||
|
||||
const expectedResult: ESTree.Literal = NodeUtils.clone(literalNode);
|
||||
|
||||
let result: ESTree.Literal;
|
||||
|
||||
before(() => {
|
||||
literalNode.parentNode = literalNode;
|
||||
|
||||
expectedResult.parentNode = expectedResult;
|
||||
NodeMetadata.set(expectedResult, {
|
||||
forceObfuscatedNode: true,
|
||||
ignoredNode: false
|
||||
});
|
||||
|
||||
result = <ESTree.Literal>obfuscatingGuardsTransformer
|
||||
.transformNode(literalNode, literalNode);
|
||||
});
|
||||
|
||||
it('should add `forceObfuscatedNode` property with `true` value to given node', () => {
|
||||
assert.deepEqual(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: ignored node and force obfuscated node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(ignoredAndForceObfuscatedString);
|
||||
|
||||
const expectedResult: ESTree.Literal = NodeUtils.clone(literalNode);
|
||||
|
||||
let result: ESTree.Literal;
|
||||
|
||||
before(() => {
|
||||
literalNode.parentNode = literalNode;
|
||||
|
||||
expectedResult.parentNode = expectedResult;
|
||||
NodeMetadata.set(expectedResult, {
|
||||
forceObfuscatedNode: false,
|
||||
ignoredNode: true
|
||||
});
|
||||
|
||||
result = <ESTree.Literal>obfuscatingGuardsTransformer
|
||||
.transformNode(literalNode, literalNode);
|
||||
});
|
||||
|
||||
it('should add `ignoredNode` property with `true` value to given node', () => {
|
||||
assert.deepEqual(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,50 @@ import { NodeFactory } from '../../../../src/node/NodeFactory';
|
||||
import { NodeLiteralUtils } from '../../../../src/node/NodeLiteralUtils';
|
||||
|
||||
describe('NodeLiteralUtils', () => {
|
||||
describe('isStringLiteralNode', () => {
|
||||
describe('Variant #1: string literal node', () => {
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
|
||||
result = NodeLiteralUtils.isStringLiteralNode(literalNode);
|
||||
});
|
||||
|
||||
it('should return `true` for string literal node', () => {
|
||||
assert.isTrue(result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: number literal node', () => {
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(123);
|
||||
|
||||
result = NodeLiteralUtils.isStringLiteralNode(literalNode);
|
||||
});
|
||||
|
||||
it('should return `false` for number literal node', () => {
|
||||
assert.isFalse(result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: boolean literal node', () => {
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(true);
|
||||
|
||||
result = NodeLiteralUtils.isStringLiteralNode(literalNode);
|
||||
});
|
||||
|
||||
it('should return `false` for boolean literal node', () => {
|
||||
assert.isFalse(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isProhibitedLiteralNode', () => {
|
||||
describe('String literal node', () => {
|
||||
describe('Variant #1: base string literal node', () => {
|
||||
|
||||
@@ -47,6 +47,24 @@ describe('NodeMetadata', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isForceObfuscatedNode', () => {
|
||||
const expectedValue: boolean = true;
|
||||
|
||||
let node: ESTree.Identifier,
|
||||
value: boolean | undefined;
|
||||
|
||||
before(() => {
|
||||
node = NodeFactory.identifierNode('foo');
|
||||
node.metadata = {};
|
||||
node.metadata.forceObfuscatedNode = true;
|
||||
value = NodeMetadata.isForceObfuscatedNode(node);
|
||||
});
|
||||
|
||||
it('should return metadata value', () => {
|
||||
assert.equal(value, expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isIgnoredNode', () => {
|
||||
const expectedValue: boolean = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user