Fixed CLI --options-preset not applying preset values for options not explicitly set via command line (#1395)

This commit is contained in:
Timofey Kachalov
2026-03-22 12:10:12 +04:00
committed by GitHub
parent b4993e6798
commit aa3c9fd344
4 changed files with 69 additions and 7 deletions
+1
View File
@@ -7,6 +7,7 @@ v5.4.0
* Fixed `reservedNames` not preserving class method and property names when `stringArray` or `deadCodeInjection` is enabled. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1279
* Fixed infinite loop / stack overflow when `reservedNames` patterns match all generated identifier names. Now throws a descriptive error instead. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1382
* Fixed `transformObjectKeys` changing evaluation order when object expression is inside a sequence expression with preceding side effects (e.g. `return aux(ys), { min }`). Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1246
* Fixed CLI `--options-preset` not applying preset values for options not explicitly set via command line (e.g. `splitStrings` from `high-obfuscation` preset was ignored). Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1236
* Replaced `mkdirp` dependency with native `fs.mkdirSync({ recursive: true })`. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1275. Thank you https://github.com/roli-lpci!
* Replaced `conf` dependency with custom implementation using `env-paths` and native `fs`
+21 -7
View File
@@ -4,6 +4,7 @@ import * as path from 'path';
import { TInputCLIOptions } from '../types/options/TInputCLIOptions';
import { TInputOptions } from '../types/options/TInputOptions';
import { TOptionsPreset } from '../types/options/TOptionsPreset';
import { IFileData } from '../interfaces/cli/IFileData';
import { IInitializable } from '../interfaces/IInitializable';
@@ -24,11 +25,10 @@ import { StringArrayEncoding } from '../enums/node-transformers/string-array-tra
import { StringArrayIndexesType } from '../enums/node-transformers/string-array-transformers/StringArrayIndexesType';
import { StringArrayWrappersType } from '../enums/node-transformers/string-array-transformers/StringArrayWrappersType';
import { DEFAULT_PRESET } from '../options/presets/Default';
import { ArraySanitizer } from './sanitizers/ArraySanitizer';
import { BooleanSanitizer } from './sanitizers/BooleanSanitizer';
import { Options } from '../options/Options';
import { CLIUtils } from './utils/CLIUtils';
import { IdentifierNamesCacheFileUtils } from './utils/IdentifierNamesCacheFileUtils';
import { JavaScriptObfuscator } from '../JavaScriptObfuscatorFacade';
@@ -112,26 +112,36 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
/**
* @param {TInputCLIOptions} inputOptions
* @param {commander.Command} command
* @returns {TInputOptions}
*/
private static buildOptions(inputOptions: TInputCLIOptions): TInputOptions {
const inputCLIOptions: TInputOptions = JavaScriptObfuscatorCLI.filterOptions(inputOptions);
private static buildOptions(inputOptions: TInputCLIOptions, command: commander.Command): TInputOptions {
const inputCLIOptions: TInputOptions = JavaScriptObfuscatorCLI.filterOptions(inputOptions, command);
const configFilePath: string | undefined = inputOptions.config;
const configFileLocation: string = configFilePath ? path.resolve(configFilePath, '.') : '';
const configFileOptions: TInputOptions = configFileLocation ? CLIUtils.getUserConfig(configFileLocation) : {};
const presetName: TOptionsPreset =
inputCLIOptions.optionsPreset ?? configFileOptions.optionsPreset ?? OptionsPreset.Default;
const presetOptions: TInputOptions = Options.getOptionsByPreset(presetName);
return {
...DEFAULT_PRESET,
...presetOptions,
...configFileOptions,
...inputCLIOptions
};
}
/**
* Filters out options that were not explicitly set by the user.
* Commander.js sets default values for all options, which would
* override preset values. Only user-provided options should be kept.
*
* @param {TObject} options
* @param {commander.Command} command
* @returns {TInputOptions}
*/
private static filterOptions(options: TInputCLIOptions): TInputOptions {
private static filterOptions(options: TInputCLIOptions, command: commander.Command): TInputOptions {
const filteredOptions: TInputOptions = {};
Object.keys(options).forEach((option: keyof TInputCLIOptions) => {
@@ -139,6 +149,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
return;
}
if (command.getOptionValueSource(String(option)) === 'default') {
return;
}
filteredOptions[option] = options[option];
});
@@ -152,7 +166,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
this.configureHelp();
this.inputPath = path.normalize(this.commands.args[0] || '');
this.inputCLIOptions = JavaScriptObfuscatorCLI.buildOptions(this.commands.opts());
this.inputCLIOptions = JavaScriptObfuscatorCLI.buildOptions(this.commands.opts(), this.commands);
this.sourceCodeFileUtils = new SourceCodeFileUtils(this.inputPath, this.inputCLIOptions);
this.obfuscatedCodeFileUtils = new ObfuscatedCodeFileUtils(this.inputPath, this.inputCLIOptions);
this.identifierNamesCacheFileUtils = new IdentifierNamesCacheFileUtils(
+2
View File
@@ -0,0 +1,2 @@
var x = "This is a long string and it should really be split by the obfuscator";
console.log(x);
@@ -1511,6 +1511,51 @@ describe('JavaScriptObfuscatorCLI', function (): void {
});
});
/**
* https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1236
*/
describe('`--options-preset` should apply preset options that are not explicitly set via CLI', () => {
const longStringFixturePath: string = path.join(fixturesDirName, 'sample-long-string.js');
let obfuscatedCode: string;
before(async () => {
await JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
longStringFixturePath,
'--output',
outputFilePath,
'--options-preset',
'medium-obfuscation',
'--string-array',
'false',
'--dead-code-injection',
'false',
'--control-flow-flattening',
'false',
'--self-defending',
'false',
'--debug-protection',
'false',
'--disable-console-output',
'false',
'--seed',
'1'
]);
obfuscatedCode = fs.readFileSync(outputFilePath, 'utf8');
});
it('should apply `splitStrings` from preset without explicit `--split-strings` flag', () => {
assert.match(obfuscatedCode, /'.+'\s*\+\s*'.+'\s*\+\s*'.+'/);
});
after(() => {
fs.unlinkSync(outputFilePath);
});
});
after(() => {
rimraf.sync(outputDirName);
});