Skip to content

Commit 5b5d0eb

Browse files
authored
Merge pull request javascript-obfuscator#927 from javascript-obfuscator/names-cache
Identifier names cache option
2 parents e7dfd04 + a04dd87 commit 5b5d0eb

File tree

84 files changed

+2611
-325
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2611
-325
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
Change Log
22

3+
v2.14.0
4+
---
5+
* Added `identifierNamesCache` option for reading and writing identifier names cache. See `README.md`.
6+
* **CLI**: Added `--identifier-names-cache-path` option for reading and writing identifier names cache. See `README.md`.
7+
38
v2.13.0
49
---
510
* Fixed invalid code generation for start/middle rest arguments when `controlFlowFlattenig` option is enabled. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/920

README.md

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ function _0x1054 (_0x14a2a4, _0x5a6b22) {
230230
Returns `ObfuscationResult` object which contains two public methods:
231231

232232
* `getObfuscatedCode()` - returns `string` with obfuscated code;
233-
* `getSourceMap()` - if [`sourceMap`](#sourcemap) option is enabled - returns `string` with source map or an empty string if [`sourceMapMode`](#sourcemapmode) option is set as `inline`.
233+
* `getSourceMap()` - if [`sourceMap`](#sourcemap) option is enabled - returns `string` with source map or an empty string if [`sourceMapMode`](#sourcemapmode) option is set as `inline`;
234+
* `getIdentifierNamesCache()` - returns object with identifier names cache if `identifierNamesCache` option is enabled, `null` overwise.
234235

235236
Calling `toString()` for `ObfuscationResult` object will return `string` with obfuscated code.
236237

@@ -361,6 +362,7 @@ Following options are available for the JS Obfuscator:
361362
disableConsoleOutput: false,
362363
domainLock: [],
363364
forceTransformStrings: [],
365+
identifierNamesCache: null,
364366
identifierNamesGenerator: 'hexadecimal',
365367
identifiersDictionary: [],
366368
identifiersPrefix: '',
@@ -421,6 +423,7 @@ Following options are available for the JS Obfuscator:
421423
--domain-lock '<list>' (comma separated)
422424
--exclude '<list>' (comma separated)
423425
--force-transform-strings '<list>' (comma separated)
426+
--identifier-names-cache-path <string>
424427
--identifier-names-generator <string> [dictionary, hexadecimal, mangled, mangled-shuffled]
425428
--identifiers-dictionary '<list>' (comma separated)
426429
--identifiers-prefix <string>
@@ -712,6 +715,84 @@ Example:
712715
}
713716
```
714717

718+
### `identifierNamesCache`
719+
Type: `Object | null` Default: `null`
720+
721+
The main goal for this option is the ability to use the same identifier names during obfuscation of multiple sources/files.
722+
723+
Currently the two types of the identifiers are supported:
724+
- Global identifiers:
725+
* All global identifiers will be written to the cache;
726+
* All matched **undeclared** global identifiers will be replaced by the values from the cache.
727+
- Property identifiers, only when `renameProperties` option is enabled:
728+
* All property identifiers will be written to the cache;
729+
* All matched property identifiers will be replaced by the values from the cache.
730+
731+
#### Node.js API
732+
If a `null` value is passed, completely disables the cache.
733+
734+
If an empty object (`{}`) is passed, enables the writing identifier names to the cache-object (`TIdentifierNamesCache` type). This cache-object will be accessed through the `getIdentifierNamesCache` method call of `ObfuscationResult` object.
735+
736+
The resulting cache-object can be next used as `identifierNamesGenerator` option value for using these names during obfuscation of all matched identifier names of next sources.
737+
738+
Example:
739+
```
740+
const source1ObfuscationResult = JavaScriptObfuscator.obfuscate(
741+
`
742+
function foo(arg) {
743+
console.log(arg)
744+
}
745+
746+
function bar() {
747+
var bark = 2;
748+
}
749+
`,
750+
{
751+
compact: false,
752+
identifierNamesCache: {},
753+
renameGlobals: true
754+
}
755+
)
756+
757+
console.log(source1ObfuscationResult.getIdentifierNamesCache());
758+
/*{
759+
globalIdentifiers: {
760+
foo: '_0x5de86d',
761+
bar: '_0x2a943b'
762+
}
763+
}*/
764+
765+
766+
767+
const source2ObfuscationResult = JavaScriptObfuscator.obfuscate(
768+
`
769+
// Expecting that these global functions are defined in another obfuscated file
770+
foo(1);
771+
bar();
772+
773+
// Expecting that this global function is defined in third-party package
774+
baz();
775+
`,
776+
{
777+
compact: false,
778+
identifierNamesCache: source1ObfuscationResult.getIdentifierNamesCache(),
779+
renameGlobals: true
780+
}
781+
)
782+
783+
console.log(source2ObfuscationResult.getObfuscatedCode());
784+
// _0x5de86d(0x1);
785+
// _0x2a943b();
786+
// baz();
787+
```
788+
789+
#### CLI
790+
CLI has a different option `--identifier-names-cache-path` that allows defining a path to the existing `.json` file that will be used to read and write identifier names cache.
791+
792+
If a path to the empty file will be passed - identifier names cache will be written to that file.
793+
794+
This file with existing cache can be used again as `--identifier-names-cache-path` option value for using these names during obfuscation of all matched identifier names of the next files.
795+
715796
### `identifierNamesGenerator`
716797
Type: `string` Default: `hexadecimal`
717798

@@ -834,6 +915,8 @@ Specifies `renameProperties` option mode:
834915
* `safe` - default behaviour after `2.11.0` release. Trying to rename properties in a more safe way to prevent runtime errors. With this mode some properties will be excluded from renaming.
835916
* `unsafe` - default behaviour before `2.11.0` release. Renames properties in an unsafe way without any restrictions.
836917

918+
If one file is using properties from other file, use [`identifierNamesCache`](#identifiernamescache) option to keep the same property names between these files.
919+
837920
### `reservedNames`
838921
Type: `string[]` Default: `[]`
839922

dist/index.browser.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.cli.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import { TInputOptions } from './src/types/options/TInputOptions';
33
import { TObfuscationResultsObject } from './src/types/TObfuscationResultsObject';
44
import { TOptionsPreset } from './src/types/options/TOptionsPreset';
55

6-
import { IObfuscatedCode } from './src/interfaces/source-code/IObfuscatedCode';
6+
import { IObfuscationResult } from './src/interfaces/source-code/IObfuscationResult';
77

88
export type ObfuscatorOptions = TInputOptions;
99

10-
export interface ObfuscatedCode extends IObfuscatedCode {}
10+
export interface ObfuscationResult extends IObfuscationResult {}
1111

1212
/**
1313
* @param {string} sourceCode
1414
* @param {ObfuscatorOptions} inputOptions
1515
* @returns {ObfuscatedCode}
1616
*/
17-
export function obfuscate (sourceCode: string, inputOptions?: ObfuscatorOptions): ObfuscatedCode;
17+
export function obfuscate (sourceCode: string, inputOptions?: ObfuscatorOptions): ObfuscationResult;
1818

1919
/**
2020
* @param {TSourceCodesObject} sourceCodesObject

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "javascript-obfuscator",
3-
"version": "2.13.0",
3+
"version": "2.14.0",
44
"description": "JavaScript obfuscator",
55
"keywords": [
66
"obfuscator",
@@ -24,7 +24,7 @@
2424
"@javascript-obfuscator/escodegen": "2.2.0",
2525
"@javascript-obfuscator/estraverse": "5.3.0",
2626
"@nuxtjs/opencollective": "0.3.2",
27-
"acorn": "8.2.4",
27+
"acorn": "8.3.0",
2828
"assert": "2.0.0",
2929
"chalk": "4.1.1",
3030
"chance": "1.1.7",
@@ -68,8 +68,8 @@
6868
"chai-exclude": "2.0.3",
6969
"cross-env": "7.0.3",
7070
"eslint": "7.27.0",
71-
"eslint-plugin-import": "2.23.3",
72-
"eslint-plugin-jsdoc": "35.0.0",
71+
"eslint-plugin-import": "2.23.4",
72+
"eslint-plugin-jsdoc": "35.1.0",
7373
"eslint-plugin-no-null": "1.0.2",
7474
"eslint-plugin-prefer-arrow": "1.2.3",
7575
"eslint-plugin-unicorn": "32.0.1",

src/JavaScriptObfuscator.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import * as acorn from 'acorn';
55
import * as escodegen from '@javascript-obfuscator/escodegen';
66
import * as ESTree from 'estree';
77

8-
import { TObfuscatedCodeFactory } from './types/container/source-code/TObfuscatedCodeFactory';
8+
import { TObfuscationResultFactory } from './types/container/source-code/TObfuscationResultFactory';
99

1010
import { ICodeTransformersRunner } from './interfaces/code-transformers/ICodeTransformersRunner';
1111
import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
1212
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
1313
import { ILogger } from './interfaces/logger/ILogger';
14-
import { IObfuscatedCode } from './interfaces/source-code/IObfuscatedCode';
14+
import { IObfuscationResult } from './interfaces/source-code/IObfuscationResult';
1515
import { IOptions } from './interfaces/options/IOptions';
1616
import { IRandomGenerator } from './interfaces/utils/IRandomGenerator';
1717
import { INodeTransformersRunner } from './interfaces/node-transformers/INodeTransformersRunner';
@@ -87,6 +87,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
8787
NodeTransformer.ObjectPatternPropertiesTransformer,
8888
NodeTransformer.ParentificationTransformer,
8989
NodeTransformer.ScopeIdentifiersTransformer,
90+
NodeTransformer.ScopeThroughIdentifiersTransformer,
9091
NodeTransformer.SplitStringTransformer,
9192
NodeTransformer.StringArrayRotateFunctionTransformer,
9293
NodeTransformer.StringArrayScopeCallsWrapperTransformer,
@@ -108,9 +109,9 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
108109
private readonly logger: ILogger;
109110

110111
/**
111-
* @type {TObfuscatedCodeFactory}
112+
* @type {TObfuscationResultFactory}
112113
*/
113-
private readonly obfuscatedCodeFactory: TObfuscatedCodeFactory;
114+
private readonly obfuscationResultFactory: TObfuscationResultFactory;
114115

115116
/**
116117
* @type {IOptions}
@@ -131,31 +132,31 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
131132
* @param {ICodeTransformersRunner} codeTransformersRunner
132133
* @param {INodeTransformersRunner} nodeTransformersRunner
133134
* @param {IRandomGenerator} randomGenerator
134-
* @param {TObfuscatedCodeFactory} obfuscatedCodeFactory
135+
* @param {TObfuscationResultFactory} obfuscatedCodeFactory
135136
* @param {ILogger} logger
136137
* @param {IOptions} options
137138
*/
138139
public constructor (
139140
@inject(ServiceIdentifiers.ICodeTransformersRunner) codeTransformersRunner: ICodeTransformersRunner,
140141
@inject(ServiceIdentifiers.INodeTransformersRunner) nodeTransformersRunner: INodeTransformersRunner,
141142
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
142-
@inject(ServiceIdentifiers.Factory__IObfuscatedCode) obfuscatedCodeFactory: TObfuscatedCodeFactory,
143+
@inject(ServiceIdentifiers.Factory__IObfuscationResult) obfuscatedCodeFactory: TObfuscationResultFactory,
143144
@inject(ServiceIdentifiers.ILogger) logger: ILogger,
144145
@inject(ServiceIdentifiers.IOptions) options: IOptions
145146
) {
146147
this.codeTransformersRunner = codeTransformersRunner;
147148
this.nodeTransformersRunner = nodeTransformersRunner;
148149
this.randomGenerator = randomGenerator;
149-
this.obfuscatedCodeFactory = obfuscatedCodeFactory;
150+
this.obfuscationResultFactory = obfuscatedCodeFactory;
150151
this.logger = logger;
151152
this.options = options;
152153
}
153154

154155
/**
155156
* @param {string} sourceCode
156-
* @returns {IObfuscatedCode}
157+
* @returns {IObfuscationResult}
157158
*/
158-
public obfuscate (sourceCode: string): IObfuscatedCode {
159+
public obfuscate (sourceCode: string): IObfuscationResult {
159160
if (typeof sourceCode !== 'string') {
160161
sourceCode = '';
161162
}
@@ -183,7 +184,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
183184
const obfuscationTime: number = (Date.now() - timeStart) / 1000;
184185
this.logger.success(LoggingMessage.ObfuscationCompleted, obfuscationTime);
185186

186-
return this.getObfuscatedCode(generatorOutput);
187+
return this.getObfuscationResult(generatorOutput);
187188
}
188189

189190
/**
@@ -268,10 +269,10 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
268269

269270
/**
270271
* @param {IGeneratorOutput} generatorOutput
271-
* @returns {IObfuscatedCode}
272+
* @returns {IObfuscationResult}
272273
*/
273-
private getObfuscatedCode (generatorOutput: IGeneratorOutput): IObfuscatedCode {
274-
return this.obfuscatedCodeFactory(generatorOutput.code, generatorOutput.map);
274+
private getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult {
275+
return this.obfuscationResultFactory(generatorOutput.code, generatorOutput.map);
275276
}
276277

277278
/**

src/JavaScriptObfuscatorFacade.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { TOptionsPreset } from './types/options/TOptionsPreset';
99

1010
import { IInversifyContainerFacade } from './interfaces/container/IInversifyContainerFacade';
1111
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
12-
import { IObfuscatedCode } from './interfaces/source-code/IObfuscatedCode';
12+
import { IObfuscationResult } from './interfaces/source-code/IObfuscationResult';
1313

1414
import { InversifyContainerFacade } from './container/InversifyContainerFacade';
1515
import { Options } from './options/Options';
@@ -24,20 +24,20 @@ class JavaScriptObfuscatorFacade {
2424
/**
2525
* @param {string} sourceCode
2626
* @param {TInputOptions} inputOptions
27-
* @returns {IObfuscatedCode}
27+
* @returns {IObfuscationResult}
2828
*/
29-
public static obfuscate (sourceCode: string, inputOptions: TInputOptions = {}): IObfuscatedCode {
29+
public static obfuscate (sourceCode: string, inputOptions: TInputOptions = {}): IObfuscationResult {
3030
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
3131

3232
inversifyContainerFacade.load(sourceCode, '', inputOptions);
3333

3434
const javaScriptObfuscator: IJavaScriptObfuscator = inversifyContainerFacade
3535
.get<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator);
36-
const obfuscatedCode: IObfuscatedCode = javaScriptObfuscator.obfuscate(sourceCode);
36+
const obfuscationResult: IObfuscationResult = javaScriptObfuscator.obfuscate(sourceCode);
3737

3838
inversifyContainerFacade.unload();
3939

40-
return obfuscatedCode;
40+
return obfuscationResult;
4141
}
4242

4343
/**

0 commit comments

Comments
 (0)