Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Change Log

v5.4.7
---
* Fixed CLI `--config` failures hiding the real cause behind a generic `Cannot open config file` message. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1101
* Fixed `sourceMapFileName` ending in `.js.map` (e.g. `foo.min.js.map`) being mangled in the emitted `//# sourceMappingURL=` comment. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1312
* Fixed `URIError: URI malformed` crash when `stringArray` with `base64`/`rc4` encoding processed a string literal containing lone surrogate code units (e.g. `"[^\uD800-\uDFFF]"`). Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1431

Expand Down
44 changes: 33 additions & 11 deletions src/cli/utils/CLIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,32 @@ export class CLIUtils {
* @returns {TDictionary}
*/
public static getUserConfig(configPath: string): TDictionary {
let config: TDictionary;

const configFileExtension: string = path.extname(configPath);
const isValidExtension: boolean = CLIUtils.allowedConfigFileExtensions.includes(configFileExtension);

if (!isValidExtension) {
throw new ReferenceError('Given config path must be a valid `.js|.mjs|.cjs` or `.json` file path');
throw new ReferenceError('Given config path must be a valid `.js`, `.cjs` or `.json` file path');
}

const errors: Error[] = [];

try {
config = require(configPath);
} catch {
try {
config = __non_webpack_require__(configPath);
} catch {
throw new ReferenceError(`Cannot open config file with path: ${configPath}`);
}
return require(configPath);
} catch (error) {
errors.push(<Error>error);
}

return config;
try {
return __non_webpack_require__(configPath);
} catch (error) {
errors.push(<Error>error);
}

// surface the underlying reason (invalid JSON, `ERR_REQUIRE_ESM`, missing file, ...)
// instead of masking it behind a generic message
throw new ReferenceError(
`Cannot open config file with path: ${configPath}. Reason: ${CLIUtils.getConfigErrorReason(errors)}`
);
}

/**
Expand All @@ -44,4 +50,20 @@ export class CLIUtils {
public static stringifyOptionAvailableValues(optionEnum: TDictionary): string {
return Object.values(optionEnum).join(`${StringSeparator.Comma} `);
}

/**
* @param {Error[]} errors
* @returns {string}
*/
private static getConfigErrorReason(errors: Error[]): string {
const [firstError, secondError] = errors;

// in the webpack bundle the real reason comes from the `__non_webpack_require__` call (the second error);
// in a plain Node/ts-node context `__non_webpack_require__` is not defined, so the real reason is the first error
if (secondError && !secondError.message.includes('__non_webpack_require__')) {
return secondError.message;
}

return firstError.message;
}
}
5 changes: 5 additions & 0 deletions test/fixtures/invalid-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
compact: true,
selfDefending: false,
sourceMap: true
}
21 changes: 21 additions & 0 deletions test/unit-tests/cli/utils/CLIUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,27 @@ describe('CLIUtils', () => {
assert.throws(testFunc, /Cannot open config file/);
});
});

// https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1101
describe('Variant #4: config file with invalid content', () => {
const configDirName: string = 'test/fixtures';
const configFileName: string = 'invalid-config.json';
const configFilePath: string = `../../../${configDirName}/${configFileName}`;

let testFunc: () => void;

before(() => {
testFunc = () => CLIUtils.getUserConfig(configFilePath);
});

it('should throw an error that includes the config file path', () => {
assert.throws(testFunc, /Cannot open config file with path/);
});

it('should surface the underlying reason instead of masking it', () => {
assert.throws(testFunc, /Reason:.*JSON/);
});
});
});

describe('stringifyOptionAvailableValues', () => {
Expand Down
Loading