More stable way to preserve identifiers with scope identifiers traverser

This commit is contained in:
sanex3339
2020-02-13 01:57:36 +03:00
parent eb233be65a
commit 89e8a2452a
21 changed files with 3982 additions and 154 deletions
+5 -5
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="test-obfuscated.js"></script>
</head>
<body>
</body>
</html>
@@ -7,6 +7,7 @@ import { convertingTransformersModule } from './modules/node-transformers/Conver
import { customNodesModule } from './modules/custom-nodes/CustomNodesModule';
import { finalizingTransformersModule } from './modules/node-transformers/FinalizingTransformersModule';
import { generatorsModule } from './modules/generators/GeneratorsModule';
import { nodeModule } from './modules/node/NodeModule';
import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
import { obfuscatingTransformersModule } from './modules/node-transformers/ObfuscatingTransformersModule';
import { optionsModule } from './modules/options/OptionsModule';
@@ -196,6 +197,7 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
this.container.load(customNodesModule);
this.container.load(finalizingTransformersModule);
this.container.load(generatorsModule);
this.container.load(nodeModule);
this.container.load(nodeTransformersModule);
this.container.load(obfuscatingTransformersModule);
this.container.load(optionsModule);
+1
View File
@@ -39,6 +39,7 @@ export enum ServiceIdentifiers {
IPrevailingKindOfVariablesAnalyzer = 'IPrevailingKindOfVariablesAnalyzer',
IObjectExpressionExtractor = 'IObjectExpressionExtractor',
IRandomGenerator = 'IRandomGenerator',
IScopeIdentifiersTraverser = 'IScopeIdentifiersTraverser',
ISourceCode = 'ISourceCode',
ISourceMapCorrector = 'ISourceMapCorrector',
IScopeAnalyzer = 'IScopeAnalyzer',
+13
View File
@@ -0,0 +1,13 @@
import { ContainerModule, interfaces } from 'inversify';
import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { IScopeIdentifiersTraverser } from '../../../interfaces/node/IScopeIdentifiersTraverser';
import { ScopeIdentifiersTraverser } from '../../../node/ScopeIdentifiersTraverser';
export const nodeModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// scope identifiers traverser
bind<IScopeIdentifiersTraverser>(ServiceIdentifiers.IScopeIdentifiersTraverser)
.to(ScopeIdentifiersTraverser)
.inSingletonScope();
});
@@ -0,0 +1,17 @@
import * as ESTree from 'estree';
import { TScopeIdentifiersTraverserCallback } from '../../types/node/TScopeIdentifiersTraverserCallback';
export interface IScopeIdentifiersTraverser {
/**
* @param {Program} programNode
* @param {Node | null} parentNode
* @param {TScopeIdentifiersTraverserCallback} callback
*/
traverse (
programNode: ESTree.Program,
parentNode: ESTree.Node | null,
callback: TScopeIdentifiersTraverserCallback
): void;
}
@@ -0,0 +1,11 @@
import * as eslintScope from 'eslint-scope';
import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
export interface IScopeIdentifiersTraverserCallbackData {
isGlobalDeclaration: boolean;
rootScope: eslintScope.Scope;
variable: eslintScope.Variable;
variableLexicalScopeNode: TNodeWithLexicalScope;
variableScope: eslintScope.Scope;
}
@@ -11,7 +11,8 @@ import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IScopeAnalyzer } from '../../interfaces/analyzers/scope-analyzer/IScopeAnalyzer';
import { IScopeIdentifiersTraverser } from '../../interfaces/node/IScopeIdentifiersTraverser';
import { IScopeIdentifiersTraverserCallbackData } from '../../interfaces/node/IScopeIdentifiersTraverserCallbackData';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { IdentifierObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer';
@@ -26,19 +27,6 @@ import { NodeMetadata } from '../../node/NodeMetadata';
*/
@injectable()
export class ScopeIdentifiersTransformer extends AbstractNodeTransformer {
/**
* @type {string}
*/
private static readonly argumentsVariableName: string = 'arguments';
/**
* @type {string[]}
*/
private static readonly globalScopeNames: string[] = [
'global',
'module'
];
/**
* @type {IIdentifierObfuscatingReplacer}
*/
@@ -50,29 +38,29 @@ export class ScopeIdentifiersTransformer extends AbstractNodeTransformer {
private readonly lexicalScopesWithObjectPatternWithoutDeclarationMap: Map<TNodeWithLexicalScope, boolean> = new Map();
/**
* @type {IScopeAnalyzer}
* @type {IScopeIdentifiersTraverser}
*/
private readonly scopeAnalyzer: IScopeAnalyzer;
private readonly scopeIdentifiersTraverser: IScopeIdentifiersTraverser;
/**
* @param {TIdentifierObfuscatingReplacerFactory} identifierObfuscatingReplacerFactory
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {IScopeAnalyzer} scopeAnalyzer
* @param {IScopeIdentifiersTraverser} scopeIdentifiersTraverser
*/
public constructor (
@inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.IScopeAnalyzer) scopeAnalyzer: IScopeAnalyzer
@inject(ServiceIdentifiers.IScopeIdentifiersTraverser) scopeIdentifiersTraverser: IScopeIdentifiersTraverser
) {
super(randomGenerator, options);
this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer
);
this.scopeAnalyzer = scopeAnalyzer;
this.scopeIdentifiersTraverser = scopeIdentifiersTraverser;
}
/**
@@ -85,8 +73,6 @@ export class ScopeIdentifiersTransformer extends AbstractNodeTransformer {
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
if (parentNode && NodeGuards.isProgramNode(node)) {
this.analyzeNode(node, parentNode);
return this.transformNode(node, parentNode);
}
}
@@ -97,68 +83,46 @@ export class ScopeIdentifiersTransformer extends AbstractNodeTransformer {
}
}
/**
* @param {Program} programNode
* @param {Node | null} parentNode
* @returns {Node}
*/
public analyzeNode (programNode: ESTree.Program, parentNode: ESTree.Node | null): void {
this.scopeAnalyzer.analyze(programNode);
}
/**
* @param {VariableDeclaration} programNode
* @param {NodeGuards} parentNode
* @returns {NodeGuards}
*/
public transformNode (programNode: ESTree.Program, parentNode: ESTree.Node): ESTree.Node {
const globalScope: eslintScope.Scope = this.scopeAnalyzer.acquireScope(programNode);
this.scopeIdentifiersTraverser.traverse(
programNode,
parentNode,
(data: IScopeIdentifiersTraverserCallbackData) => {
const {
isGlobalDeclaration,
variable,
variableLexicalScopeNode
} = data;
this.traverseScopeVariables(globalScope);
if (!this.options.renameGlobals && isGlobalDeclaration) {
const isImportBindingOrCatchClauseIdentifier: boolean = variable.defs
.every((definition: eslintScope.Definition) =>
definition.type === 'ImportBinding'
|| definition.type === 'CatchClause'
);
// skip all global identifiers except import statement and catch clause parameter identifiers
if (!isImportBindingOrCatchClauseIdentifier) {
return;
}
}
this.transformScopeVariableIdentifiers(
variable,
variableLexicalScopeNode,
isGlobalDeclaration
);
}
);
return programNode;
}
/**
* @param {Scope} scope
*/
private traverseScopeVariables (scope: eslintScope.Scope): void {
const lexicalScope: eslintScope.Scope = scope.variableScope;
const nodeWithLexicalScope: TNodeWithLexicalScope | null = NodeGuards.isNodeWithBlockLexicalScope(lexicalScope.block)
? lexicalScope.block
: null;
const isGlobalDeclaration: boolean = ScopeIdentifiersTransformer.globalScopeNames.includes(lexicalScope.type);
if (!nodeWithLexicalScope) {
return;
}
for (const variable of scope.variables) {
if (variable.name === ScopeIdentifiersTransformer.argumentsVariableName) {
continue;
}
if (!this.options.renameGlobals && isGlobalDeclaration) {
const isImportBindingOrCatchClauseIdentifier: boolean = variable.defs
.every((definition: eslintScope.Definition) =>
definition.type === 'ImportBinding'
|| definition.type === 'CatchClause'
);
// skip all global identifiers except import statement and catch clause parameter identifiers
if (!isImportBindingOrCatchClauseIdentifier) {
continue;
}
}
this.transformScopeVariableIdentifiers(variable, nodeWithLexicalScope, isGlobalDeclaration);
}
for (const childScope of scope.childScopes) {
this.traverseScopeVariables(childScope);
}
}
/**
* @param {Variable} variable
* @param {TNodeWithLexicalScope} lexicalScopeNode
@@ -1,5 +1,6 @@
import { inject, injectable, } from 'inversify';
import * as ESTree from 'estree';
import * as eslintScope from 'eslint-scope';
import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory';
import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
@@ -8,12 +9,14 @@ import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transforme
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { IdentifierObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer';
import { IScopeIdentifiersTraverser } from '../../interfaces/node/IScopeIdentifiersTraverser';
import { IScopeIdentifiersTraverserCallbackData } from '../../interfaces/node/IScopeIdentifiersTraverserCallbackData';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { IdentifierObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer';
import { NodeGuards } from '../../node/NodeGuards';
/**
@@ -21,32 +24,35 @@ import { NodeGuards } from '../../node/NodeGuards';
*/
@injectable()
export class VariablePreserveTransformer extends AbstractNodeTransformer {
/**
* @type {TNodeWithLexicalScope[]}
*/
private readonly enteredLexicalScopesStack: TNodeWithLexicalScope[] = [];
/**
* @type {IIdentifierObfuscatingReplacer}
*/
private readonly identifierObfuscatingReplacer: IIdentifierObfuscatingReplacer;
/**
* @type {IScopeIdentifiersTraverser}
*/
private readonly scopeIdentifiersTraverser: IScopeIdentifiersTraverser;
/**
* @param {TIdentifierObfuscatingReplacerFactory} identifierObfuscatingReplacerFactory
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {IScopeIdentifiersTraverser} scopeIdentifiersTraverser
*/
public constructor (
@inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.IScopeIdentifiersTraverser) scopeIdentifiersTraverser: IScopeIdentifiersTraverser
) {
super(randomGenerator, options);
this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer
);
this.scopeIdentifiersTraverser = scopeIdentifiersTraverser;
}
/**
@@ -58,29 +64,9 @@ export class VariablePreserveTransformer extends AbstractNodeTransformer {
case TransformationStage.Preparing:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
if (NodeGuards.isNodeWithLexicalScope(node)) {
this.addLexicalScopeToEnteredLexicalScopesStack(node);
}
if (
NodeGuards.isIdentifierNode(node)
&& parentNode
) {
const isOnTheRootLexicalScope: boolean = this.enteredLexicalScopesStack.length === 1;
if (isOnTheRootLexicalScope) {
this.preserveIdentifierNameForRootLexicalScope(node, parentNode);
} else {
this.preserveIdentifierNameForLexicalScope(node, parentNode);
}
if (parentNode && NodeGuards.isProgramNode(node)) {
return this.transformNode(node, parentNode);
}
},
leave: (node: ESTree.Node): void => {
if (NodeGuards.isNodeWithLexicalScope(node)) {
this.removeLexicalScopeFromEnteredLexicalScopesStack(node);
}
}
};
@@ -90,49 +76,74 @@ export class VariablePreserveTransformer extends AbstractNodeTransformer {
}
/**
* @param {Identifier} identifierNode
* @param {Node} parentNode
* @returns {Node}
* @param {VariableDeclaration} programNode
* @param {NodeGuards} parentNode
* @returns {NodeGuards}
*/
public transformNode (identifierNode: ESTree.Identifier, parentNode: ESTree.Node): ESTree.Node {
return identifierNode;
public transformNode (programNode: ESTree.Program, parentNode: ESTree.Node): ESTree.Node {
this.scopeIdentifiersTraverser.traverse(
programNode,
parentNode,
(data: IScopeIdentifiersTraverserCallbackData) => {
const {
isGlobalDeclaration,
variable,
variableScope
} = data;
this.preserveScopeVariableIdentifiers(
variable,
variableScope,
isGlobalDeclaration
);
}
);
return programNode;
}
/**
* @param {Variable} variable
* @param {Scope} variableScope
* @param {boolean} isGlobalDeclaration
*/
private preserveScopeVariableIdentifiers (
variable: eslintScope.Variable,
variableScope: eslintScope.Scope,
isGlobalDeclaration: boolean
): void {
for (const identifier of variable.identifiers) {
if (isGlobalDeclaration) {
this.preserveIdentifierNameForRootLexicalScope(identifier);
} else {
this.preserveIdentifierNameForLexicalScope(identifier, variableScope);
}
}
}
/**
* @param {Identifier} identifierNode
* @param {Node} parentNode
*/
private preserveIdentifierNameForRootLexicalScope (
identifierNode: ESTree.Identifier,
parentNode: ESTree.Node
): void {
private preserveIdentifierNameForRootLexicalScope (identifierNode: ESTree.Identifier): void {
this.identifierObfuscatingReplacer.preserveName(identifierNode);
}
/**
* @param {Identifier} identifierNode
* @param {Node} parentNode
* @param {Scope} variableScope
*/
private preserveIdentifierNameForLexicalScope (
identifierNode: ESTree.Identifier,
parentNode: ESTree.Node
variableScope: eslintScope.Scope
): void {
for (const lexicalScope of this.enteredLexicalScopesStack) {
this.identifierObfuscatingReplacer.preserveNameForLexicalScope(identifierNode, lexicalScope);
const lexicalScopeNode: TNodeWithLexicalScope | null = NodeGuards.isNodeWithLexicalScope(variableScope.block)
? variableScope.block
: null;
if (!lexicalScopeNode) {
return;
}
}
/**
* @param {TNodeWithLexicalScope} lexicalScopeNode
*/
private addLexicalScopeToEnteredLexicalScopesStack (lexicalScopeNode: TNodeWithLexicalScope): void {
this.enteredLexicalScopesStack.push(lexicalScopeNode);
}
/**
* @param {TNodeWithLexicalScope} lexicalScopeNode
*/
private removeLexicalScopeFromEnteredLexicalScopesStack (lexicalScopeNode: TNodeWithLexicalScope): void {
this.enteredLexicalScopesStack.pop();
this.identifierObfuscatingReplacer.preserveNameForLexicalScope(identifierNode, lexicalScopeNode);
}
}
+102
View File
@@ -0,0 +1,102 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
import * as eslintScope from 'eslint-scope';
import * as ESTree from 'estree';
import { TNodeWithLexicalScope } from '../types/node/TNodeWithLexicalScope';
import { TScopeIdentifiersTraverserCallback } from '../types/node/TScopeIdentifiersTraverserCallback';
import { IScopeAnalyzer } from '../interfaces/analyzers/scope-analyzer/IScopeAnalyzer';
import { IScopeIdentifiersTraverser } from '../interfaces/node/IScopeIdentifiersTraverser';
import { NodeGuards } from './NodeGuards';
/**
* Scope traverser
*/
@injectable()
export class ScopeIdentifiersTraverser implements IScopeIdentifiersTraverser {
/**
* @type {string}
*/
private static readonly argumentsVariableName: string = 'arguments';
/**
* @type {string[]}
*/
private static readonly globalScopeNames: string[] = [
'global',
'module'
];
/**
* @type {IScopeAnalyzer}
*/
private readonly scopeAnalyzer: IScopeAnalyzer;
/**
* @param {IScopeAnalyzer} scopeAnalyzer
*/
public constructor (
@inject(ServiceIdentifiers.IScopeAnalyzer) scopeAnalyzer: IScopeAnalyzer
) {
this.scopeAnalyzer = scopeAnalyzer;
}
/**
* @param {Program} programNode
* @param {Node | null} parentNode
* @param {TScopeIdentifiersTraverserCallback} callback
*/
public traverse (
programNode: ESTree.Program,
parentNode: ESTree.Node | null,
callback: TScopeIdentifiersTraverserCallback
): void {
this.scopeAnalyzer.analyze(programNode);
const globalScope: eslintScope.Scope = this.scopeAnalyzer.acquireScope(programNode);
this.traverseScopeVariables(globalScope, globalScope, callback);
}
/**
* @param {Scope} rootScope
* @param {Scope} currentScope
* @param {TScopeIdentifiersTraverserCallback} callback
*/
private traverseScopeVariables (
rootScope: eslintScope.Scope,
currentScope: eslintScope.Scope,
callback: TScopeIdentifiersTraverserCallback
): void {
const variableScope: eslintScope.Scope = currentScope.variableScope;
const variableLexicalScopeNode: TNodeWithLexicalScope | null = NodeGuards.isNodeWithBlockLexicalScope(variableScope.block)
? variableScope.block
: null;
const isGlobalDeclaration: boolean = ScopeIdentifiersTraverser.globalScopeNames.includes(variableScope.type);
if (!variableLexicalScopeNode) {
return;
}
for (const variable of currentScope.variables) {
if (variable.name === ScopeIdentifiersTraverser.argumentsVariableName) {
continue;
}
callback({
isGlobalDeclaration,
rootScope,
variable,
variableScope,
variableLexicalScopeNode
});
}
for (const childScope of currentScope.childScopes) {
this.traverseScopeVariables(rootScope, childScope, callback);
}
}
}
@@ -0,0 +1,3 @@
import { IScopeIdentifiersTraverserCallbackData } from '../../interfaces/node/IScopeIdentifiersTraverserCallbackData';
export type TScopeIdentifiersTraverserCallback = (data: IScopeIdentifiersTraverserCallbackData) => void;
+2356
View File
File diff suppressed because it is too large Load Diff
+1308
View File
File diff suppressed because it is too large Load Diff
+5 -11
View File
@@ -7,22 +7,16 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
function a (a, b) {
}
function b (b, c) {
}
const b = function () {}
// javascript-obfuscator:disable
function a () {}
// javascript-obfuscator:enable
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
identifierNamesGenerator: 'mangled',
identifiersPrefix: 'a',
transformObjectKeys: true,
stringArray: true,
stringArrayThreshold: 1,
log: true
}
).getObfuscatedCode();
@@ -483,9 +483,9 @@ describe('ScopeIdentifiersTransformer ClassDeclaration identifiers', () => {
});
describe('Variant #3: preserved identifier names shouldn\'t be used as identifier names', () => {
const classDeclarationRegExp: RegExp = /class *f *{/;
const variableDeclarationsRegExp: RegExp = /let g, *h, *i, *j;/;
const classReferenceRegExp: RegExp = /new f\(\);/;
const classDeclarationRegExp: RegExp = /class *e *{/;
const variableDeclarationsRegExp: RegExp = /let f, *g, *h, *i;/;
const classReferenceRegExp: RegExp = /new e\(\);/;
let obfuscatedCode: string;
@@ -146,7 +146,7 @@ describe('ScopeIdentifiersTransformer FunctionDeclaration identifiers', () => {
describe('Variant #5: preserved identifier names shouldn\'t be used as identifier names', () => {
describe('Variant #1', () => {
const functionDeclarationRegExp: RegExp = /function *e\(\) *{/;
const variableDeclarationsRegExp: RegExp = /let g, *h, *i, *j;/;
const variableDeclarationsRegExp: RegExp = /let f, *g, *h, *i;/;
let obfuscatedCode: string;
@@ -456,11 +456,11 @@ describe('ScopeIdentifiersTransformer VariableDeclaration identifiers', () => {
describe('Variant #13: preserved identifier names shouldn\'t be used as identifier names', () => {
describe('Variant #1', () => {
const variableDeclarationRegExp: RegExp = /var f *= *0x1;/;
const functionDeclarationRegExp1: RegExp = /function *g *\(\) *{}/;
const functionDeclarationRegExp2: RegExp = /function *h *\(\) *{}/;
const functionDeclarationRegExp3: RegExp = /function *i *\(\) *{}/;
const functionDeclarationRegExp4: RegExp = /function *j *\(\) *{}/;
const variableDeclarationRegExp: RegExp = /var e *= *0x1;/;
const functionDeclarationRegExp1: RegExp = /function *f *\(\) *{}/;
const functionDeclarationRegExp2: RegExp = /function *g *\(\) *{}/;
const functionDeclarationRegExp3: RegExp = /function *h *\(\) *{}/;
const functionDeclarationRegExp4: RegExp = /function *i *\(\) *{}/;
let obfuscatedCode: string;
@@ -126,4 +126,34 @@ describe('VariablePreserveTransformer', () => {
});
});
});
describe('Variant #3: ignored node identifier name conflict with identifier name', () => {
describe('Variant #1: global scope', () => {
const functionExpressionIdentifierName: RegExp = /const c *= *function *\(\) *{};/;
const functionDeclarationIdentifierName: RegExp = /function a *\(\) *{}/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/ignored-node-identifier-name-1.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
identifierNamesGenerator: 'mangled',
renameGlobals: true
}
).getObfuscatedCode();
});
it('should generate non-preserved name for global identifier', () => {
assert.match(obfuscatedCode, functionExpressionIdentifierName);
});
it('should keep the original name for ignored identifier', () => {
assert.match(obfuscatedCode, functionDeclarationIdentifierName);
});
});
});
});
@@ -0,0 +1,5 @@
const b = function () {};
// javascript-obfuscator:disable
function a () {}
// javascript-obfuscator:enable