diff --git a/README.md b/README.md index d5c013bb..079ed903 100644 --- a/README.md +++ b/README.md @@ -225,20 +225,33 @@ Enables source map generation for obfuscated code. ### `sourceMapBaseUrl` Type: `string` Default: `` -Adds base url to the source map import url when `sourceMapMode: 'separate'`. +Sets base url to the source map import url when `sourceMapMode: 'separate'`. -##### :warning: this option designed for CLI usage - CLI example: ``` javascript-obfuscator input.js --output out.js --sourceMap true --sourceMapBaseUrl 'http://localhost:9000' ``` -Result import: +Result: ``` //# sourceMappingURL=http://localhost:9000/out.js.map ``` +### `sourceMapFileName` +Type: `string` Default: `` + +Sets file name for output source map when `sourceMapMode: 'separate'`. + +CLI example: +``` +javascript-obfuscator input.js --output out.js --sourceMap true --sourceMapBaseUrl 'http://localhost:9000' --sourceMapFileName example +``` + +Result: +``` +//# sourceMappingURL=http://localhost:9000/example.js.map +``` + ### `sourceMapMode` Type: `string` Default: `separate` diff --git a/dist/index.js b/dist/index.js index acfe6699..d45b78b0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -207,14 +207,6 @@ var Utils = function () { value: function isInteger(number) { return number % 1 === 0; } - }, { - key: 'normalizeUrl', - value: function normalizeUrl(url) { - if (!url.endsWith('/')) { - url += '/'; - } - return url; - } }, { key: 'strEnumify', value: function strEnumify(obj) { @@ -904,6 +896,7 @@ exports.NO_CUSTOM_NODES_PRESET = Object.freeze({ selfDefending: false, sourceMap: false, sourceMapBaseUrl: '', + sourceMapFileName: '', sourceMapMode: SourceMapMode_1.SourceMapMode.Separate, unicodeArray: false, unicodeArrayThreshold: 0, @@ -932,7 +925,6 @@ var JavaScriptObfuscatorInternal = function () { function JavaScriptObfuscatorInternal(sourceCode, obfuscatorOptions) { _classCallCheck(this, JavaScriptObfuscatorInternal); - this.sourceMapUrl = ''; this.sourceCode = sourceCode; if (obfuscatorOptions) { this.options = new Options_1.Options(obfuscatorOptions); @@ -942,10 +934,7 @@ var JavaScriptObfuscatorInternal = function () { _createClass(JavaScriptObfuscatorInternal, [{ key: 'getObfuscationResult', value: function getObfuscationResult() { - if (this.sourceMapUrl) { - this.sourceMapUrl = this.options.sourceMapBaseUrl + this.sourceMapUrl; - } - return new SourceMapCorrector_1.SourceMapCorrector(new ObfuscationResult_1.ObfuscationResult(this.generatorOutput.code, this.generatorOutput.map), this.sourceMapUrl, this.options.sourceMapMode).correct(); + return new SourceMapCorrector_1.SourceMapCorrector(new ObfuscationResult_1.ObfuscationResult(this.generatorOutput.code, this.generatorOutput.map), this.options.sourceMapBaseUrl + this.options.sourceMapFileName, this.options.sourceMapMode).correct(); } }, { key: 'obfuscate', @@ -956,11 +945,6 @@ var JavaScriptObfuscatorInternal = function () { astTree = new Obfuscator_1.Obfuscator(this.options).obfuscateNode(astTree); this.generatorOutput = JavaScriptObfuscatorInternal.generateCode(this.sourceCode, astTree, this.options); } - }, { - key: 'setSourceMapUrl', - value: function setSourceMapUrl(url) { - this.sourceMapUrl = url; - } }], [{ key: 'generateCode', value: function generateCode(sourceCode, astTree, options) { @@ -1157,6 +1141,7 @@ exports.DEFAULT_PRESET = Object.freeze({ selfDefending: true, sourceMap: false, sourceMapBaseUrl: '', + sourceMapFileName: '', sourceMapMode: SourceMapMode_1.SourceMapMode.Separate, unicodeArray: true, unicodeArrayThreshold: 0.8, @@ -1311,7 +1296,7 @@ var SourceMapCorrector = function () { _createClass(SourceMapCorrector, [{ key: "correct", value: function correct() { - return new ObfuscationResult_1.ObfuscationResult(this.correctObfuscatedCode(), this.correctSourceMap()); + return new ObfuscationResult_1.ObfuscationResult(this.correctObfuscatedCode(), this.sourceMap); } }, { key: "correctObfuscatedCode", @@ -1322,26 +1307,18 @@ var SourceMapCorrector = function () { var sourceMappingUrl = '//# sourceMappingURL='; switch (this.sourceMapMode) { case SourceMapMode_1.SourceMapMode.Inline: - sourceMappingUrl += "data:application/json;base64," + Utils_1.Utils.btoa(this.sourceMapUrl || this.sourceMap, false); + sourceMappingUrl += "data:application/json;base64," + Utils_1.Utils.btoa(this.sourceMap, false); break; case SourceMapMode_1.SourceMapMode.Separate: default: - if (this.sourceMapUrl) { - sourceMappingUrl += this.sourceMapUrl; - break; + if (!this.sourceMapUrl) { + return this.obfuscatedCode; } - return this.obfuscatedCode; + sourceMappingUrl += this.sourceMapUrl; + break; } return this.obfuscatedCode + "\n" + sourceMappingUrl; } - }, { - key: "correctSourceMap", - value: function correctSourceMap() { - if (this.sourceMapMode === SourceMapMode_1.SourceMapMode.Inline) { - return ''; - } - return this.sourceMap; - } }]); return SourceMapCorrector; @@ -1440,9 +1417,17 @@ var CLIUtils = function () { }, { key: 'getOutputSourceMapPath', value: function getOutputSourceMapPath(outputCodePath) { - return outputCodePath.split('.').map(function (value, index, array) { - return index === array.length - 1 ? value + '.map' : value; - }).join('.'); + var sourceMapFileName = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1]; + + if (sourceMapFileName) { + outputCodePath = outputCodePath.substr(0, outputCodePath.lastIndexOf('/')) + '/' + sourceMapFileName; + } + if (!/\.js\.map$/.test(outputCodePath)) { + outputCodePath = outputCodePath.split('.')[0] + '.js.map'; + } else if (/\.js$/.test(outputCodePath)) { + outputCodePath += '.map'; + } + return outputCodePath; } }, { key: 'getPackageConfig', @@ -1553,7 +1538,7 @@ var JavaScriptObfuscatorCLI = function () { value: function configureCommands() { this.commands = new commander.Command().version(JavaScriptObfuscatorCLI.getBuildVersion(), '-v, --version').usage(' [options]').option('-o, --output ', 'Output path for obfuscated code').option('--compact ', 'Disable one line output code compacting', JavaScriptObfuscatorCLI.parseBoolean).option('--debugProtection ', 'Disable browser Debug panel (can cause DevTools enabled browser freeze)', JavaScriptObfuscatorCLI.parseBoolean).option('--debugProtectionInterval ', 'Disable browser Debug panel even after page was loaded (can cause DevTools enabled browser freeze)', JavaScriptObfuscatorCLI.parseBoolean).option('--disableConsoleOutput ', 'Allow console.log, console.info, console.error and console.warn messages output into browser console', JavaScriptObfuscatorCLI.parseBoolean).option('--encodeUnicodeLiterals ', 'All literals in Unicode array become encoded in Base64 (this option can slightly slow down your code speed)', JavaScriptObfuscatorCLI.parseBoolean).option('--reservedNames ', 'Disable obfuscation of variable names, function names and names of function parameters that match the passed RegExp patterns (comma separated)', function (val) { return val.split(','); - }).option('--rotateUnicodeArray ', 'Disable rotation of unicode array values during obfuscation', JavaScriptObfuscatorCLI.parseBoolean).option('--selfDefending ', 'Disables self-defending for obfuscated code', JavaScriptObfuscatorCLI.parseBoolean).option('--sourceMap ', 'Enables source map generation', JavaScriptObfuscatorCLI.parseBoolean).option('--sourceMapBaseUrl ', 'Adds base url to the source map import url when `--sourceMapMode=separate`').option('--sourceMapMode [inline, separate]', 'Specify source map output mode', JavaScriptObfuscatorCLI.parseSourceMapMode).option('--unicodeArray ', 'Disables gathering of all literal strings into an array and replacing every literal string with an array call', JavaScriptObfuscatorCLI.parseBoolean).option('--unicodeArrayThreshold ', 'The probability that the literal string will be inserted into unicodeArray (Default: 0.8, Min: 0, Max: 1)', parseFloat).option('--wrapUnicodeArrayCalls ', 'Disables usage of special access function instead of direct array call', JavaScriptObfuscatorCLI.parseBoolean).option('--domainLock ', 'Blocks the execution of the code in domains that do not match the passed RegExp patterns (comma separated)', function (val) { + }).option('--rotateUnicodeArray ', 'Disable rotation of unicode array values during obfuscation', JavaScriptObfuscatorCLI.parseBoolean).option('--selfDefending ', 'Disables self-defending for obfuscated code', JavaScriptObfuscatorCLI.parseBoolean).option('--sourceMap ', 'Enables source map generation', JavaScriptObfuscatorCLI.parseBoolean).option('--sourceMapBaseUrl ', 'Sets base url to the source map import url when `--sourceMapMode=separate`').option('--sourceMapFileName ', 'Sets file name for output source map when `--sourceMapMode=separate`').option('--sourceMapMode [inline, separate]', 'Specify source map output mode', JavaScriptObfuscatorCLI.parseSourceMapMode).option('--unicodeArray ', 'Disables gathering of all literal strings into an array and replacing every literal string with an array call', JavaScriptObfuscatorCLI.parseBoolean).option('--unicodeArrayThreshold ', 'The probability that the literal string will be inserted into unicodeArray (Default: 0.8, Min: 0, Max: 1)', parseFloat).option('--wrapUnicodeArrayCalls ', 'Disables usage of special access function instead of direct array call', JavaScriptObfuscatorCLI.parseBoolean).option('--domainLock ', 'Blocks the execution of the code in domains that do not match the passed RegExp patterns (comma separated)', function (val) { return val.split(','); }).parse(this.rawArguments); this.commands.on('--help', function () { @@ -1588,16 +1573,13 @@ var JavaScriptObfuscatorCLI = function () { }, { key: 'processDataWithSourceMap', value: function processDataWithSourceMap(outputCodePath, options) { - var javaScriptObfuscator = new JavaScriptObfuscatorInternal_1.JavaScriptObfuscatorInternal(this.data, options), - obfuscationResult = void 0, - outputSourceMapPath = CLIUtils_1.CLIUtils.getOutputSourceMapPath(outputCodePath); + var outputSourceMapPath = CLIUtils_1.CLIUtils.getOutputSourceMapPath(outputCodePath, options.sourceMapFileName ? options.sourceMapFileName : ''); + options.sourceMapFileName = path.basename(outputSourceMapPath); + var javaScriptObfuscator = new JavaScriptObfuscatorInternal_1.JavaScriptObfuscatorInternal(this.data, options); javaScriptObfuscator.obfuscate(); - if (options.sourceMapMode === SourceMapMode_1.SourceMapMode.Separate) { - javaScriptObfuscator.setSourceMapUrl(path.basename(outputSourceMapPath)); - } - obfuscationResult = javaScriptObfuscator.getObfuscationResult(); + var obfuscationResult = javaScriptObfuscator.getObfuscationResult(); CLIUtils_1.CLIUtils.writeFile(outputCodePath, obfuscationResult.getObfuscatedCode()); - if (obfuscationResult.getSourceMap()) { + if (options.sourceMapMode === 'separate' && obfuscationResult.getSourceMap()) { CLIUtils_1.CLIUtils.writeFile(outputSourceMapPath, obfuscationResult.getSourceMap()); } } @@ -3244,6 +3226,7 @@ __decorate([class_validator_1.IsString(), class_validator_1.ValidateIf(function require_protocol: false, require_valid_protocol: true }), __metadata('design:type', String)], Options.prototype, "sourceMapBaseUrl", void 0); +__decorate([class_validator_1.IsString(), __metadata('design:type', String)], Options.prototype, "sourceMapFileName", void 0); __decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata('design:type', String)], Options.prototype, "sourceMapMode", void 0); __decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "unicodeArray", void 0); __decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata('design:type', Number)], Options.prototype, "unicodeArrayThreshold", void 0); @@ -3354,9 +3337,22 @@ var OptionsNormalizer = function () { }, { key: "sourceMapBaseUrl", value: function sourceMapBaseUrl(options) { - if (options.sourceMapBaseUrl) { + var sourceMapBaseUrl = options.sourceMapBaseUrl; + if (sourceMapBaseUrl && !sourceMapBaseUrl.endsWith('/')) { Object.assign(options, { - sourceMapBaseUrl: Utils_1.Utils.normalizeUrl(options.sourceMapBaseUrl) + sourceMapBaseUrl: sourceMapBaseUrl + "/" + }); + } + return options; + } + }, { + key: "sourceMapFileName", + value: function sourceMapFileName(options) { + var sourceMapFileName = options.sourceMapFileName; + if (sourceMapFileName) { + sourceMapFileName = sourceMapFileName.split('.')[0]; + Object.assign(options, { + sourceMapFileName: sourceMapFileName + ".js.map" }); } return options; @@ -3397,7 +3393,7 @@ OptionsNormalizer.SELF_DEFENDING_OPTIONS = { compact: true, selfDefending: true }; -OptionsNormalizer.normalizerRules = [OptionsNormalizer.domainLockRule, OptionsNormalizer.unicodeArrayRule, OptionsNormalizer.unicodeArrayThresholdRule, OptionsNormalizer.encodeUnicodeLiteralsRule, OptionsNormalizer.sourceMapBaseUrl, OptionsNormalizer.selfDefendingRule]; +OptionsNormalizer.normalizerRules = [OptionsNormalizer.domainLockRule, OptionsNormalizer.unicodeArrayRule, OptionsNormalizer.unicodeArrayThresholdRule, OptionsNormalizer.encodeUnicodeLiteralsRule, OptionsNormalizer.sourceMapBaseUrl, OptionsNormalizer.sourceMapFileName, OptionsNormalizer.selfDefendingRule]; exports.OptionsNormalizer = OptionsNormalizer; /***/ }, diff --git a/src/JavaScriptObfuscatorInternal.ts b/src/JavaScriptObfuscatorInternal.ts index c59a1b16..97601637 100644 --- a/src/JavaScriptObfuscatorInternal.ts +++ b/src/JavaScriptObfuscatorInternal.ts @@ -36,11 +36,6 @@ export class JavaScriptObfuscatorInternal { */ private sourceCode: string; - /** - * @type {string} - */ - private sourceMapUrl: string = ''; - /** * @param sourceCode * @param obfuscatorOptions @@ -84,16 +79,12 @@ export class JavaScriptObfuscatorInternal { * @returns {IObfuscationResult} */ public getObfuscationResult (): IObfuscationResult { - if (this.sourceMapUrl) { - this.sourceMapUrl = this.options.sourceMapBaseUrl + this.sourceMapUrl; - } - return new SourceMapCorrector( new ObfuscationResult( this.generatorOutput.code, this.generatorOutput.map ), - this.sourceMapUrl, + this.options.sourceMapBaseUrl + this.options.sourceMapFileName, this.options.sourceMapMode ).correct(); } @@ -107,11 +98,4 @@ export class JavaScriptObfuscatorInternal { this.generatorOutput = JavaScriptObfuscatorInternal.generateCode(this.sourceCode, astTree, this.options); } - - /** - * @param url - */ - public setSourceMapUrl (url: string): void { - this.sourceMapUrl = url; - } } diff --git a/src/SourceMapCorrector.ts b/src/SourceMapCorrector.ts index ec9f33d9..edb96c8f 100644 --- a/src/SourceMapCorrector.ts +++ b/src/SourceMapCorrector.ts @@ -52,7 +52,7 @@ export class SourceMapCorrector implements ISourceMapCorrector { public correct (): IObfuscationResult { return new ObfuscationResult( this.correctObfuscatedCode(), - this.correctSourceMap() + this.sourceMap ); } @@ -68,32 +68,21 @@ export class SourceMapCorrector implements ISourceMapCorrector { switch (this.sourceMapMode) { case SourceMapMode.Inline: - sourceMappingUrl += `data:application/json;base64,${Utils.btoa(this.sourceMapUrl || this.sourceMap, false)}`; + sourceMappingUrl += `data:application/json;base64,${Utils.btoa(this.sourceMap, false)}`; break; case SourceMapMode.Separate: default: - if (this.sourceMapUrl) { - sourceMappingUrl += this.sourceMapUrl; - - break; + if (!this.sourceMapUrl) { + return this.obfuscatedCode; } - return this.obfuscatedCode; + sourceMappingUrl += this.sourceMapUrl; + + break; } return `${this.obfuscatedCode}\n${sourceMappingUrl}`; }; - - /** - * @returns {string} - */ - private correctSourceMap (): string { - if (this.sourceMapMode === SourceMapMode.Inline) { - return ''; - } - - return this.sourceMap; - } } diff --git a/src/Utils.ts b/src/Utils.ts index 260deb95..c891c92f 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -152,18 +152,6 @@ export class Utils { return number % 1 === 0; } - /** - * @param url - * @returns {string} - */ - public static normalizeUrl (url: string): string { - if (!url.endsWith('/')) { - url += '/'; - } - - return url; - } - /** * @param obj * @returns {T} diff --git a/src/cli/CLIUtils.ts b/src/cli/CLIUtils.ts index 6b0bbc75..ea795b56 100644 --- a/src/cli/CLIUtils.ts +++ b/src/cli/CLIUtils.ts @@ -38,15 +38,24 @@ export class CLIUtils { } /** + * @param outputCodePath + * @param sourceMapFileName * @returns {string} */ - public static getOutputSourceMapPath (outputCodePath: string): string { - return outputCodePath - .split('.') - .map((value: string, index: number, array: string[]) => { - return index === array.length - 1 ? `${value}.map` : value; - }) - .join('.'); + public static getOutputSourceMapPath (outputCodePath: string, sourceMapFileName: string = ''): string { + if (sourceMapFileName) { + outputCodePath = `${outputCodePath.substr( + 0, outputCodePath.lastIndexOf('/') + )}/${sourceMapFileName}`; + } + + if (!/\.js\.map$/.test(outputCodePath)) { + outputCodePath = `${outputCodePath.split('.')[0]}.js.map`; + } else if (/\.js$/.test(outputCodePath)) { + outputCodePath += '.map'; + } + + return outputCodePath; } /** diff --git a/src/cli/JavaScriptObfuscatorCLI.ts b/src/cli/JavaScriptObfuscatorCLI.ts index 4dfd1f4b..a7a0c592 100644 --- a/src/cli/JavaScriptObfuscatorCLI.ts +++ b/src/cli/JavaScriptObfuscatorCLI.ts @@ -132,7 +132,8 @@ export class JavaScriptObfuscatorCLI { .option('--rotateUnicodeArray ', 'Disable rotation of unicode array values during obfuscation', JavaScriptObfuscatorCLI.parseBoolean) .option('--selfDefending ', 'Disables self-defending for obfuscated code', JavaScriptObfuscatorCLI.parseBoolean) .option('--sourceMap ', 'Enables source map generation', JavaScriptObfuscatorCLI.parseBoolean) - .option('--sourceMapBaseUrl ', 'Adds base url to the source map import url when `--sourceMapMode=separate`') + .option('--sourceMapBaseUrl ', 'Sets base url to the source map import url when `--sourceMapMode=separate`') + .option('--sourceMapFileName ', 'Sets file name for output source map when `--sourceMapMode=separate`') .option( '--sourceMapMode [inline, separate]', 'Specify source map output mode', @@ -182,23 +183,25 @@ export class JavaScriptObfuscatorCLI { * @param options */ private processDataWithSourceMap (outputCodePath: string, options: IObfuscatorOptions): void { - let javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal(this.data, options), - obfuscationResult: IObfuscationResult, - outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(outputCodePath); + let outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath( + outputCodePath, + options.sourceMapFileName ? options.sourceMapFileName : '' + ); + + options.sourceMapFileName = path.basename(outputSourceMapPath); + + const javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal( + this.data, + options + ); javaScriptObfuscator.obfuscate(); - if (options.sourceMapMode === SourceMapMode.Separate) { - javaScriptObfuscator.setSourceMapUrl( - path.basename(outputSourceMapPath) - ); - } - - obfuscationResult = javaScriptObfuscator.getObfuscationResult(); + const obfuscationResult: IObfuscationResult = javaScriptObfuscator.getObfuscationResult(); CLIUtils.writeFile(outputCodePath, obfuscationResult.getObfuscatedCode()); - if (obfuscationResult.getSourceMap()) { + if (options.sourceMapMode === 'separate' && obfuscationResult.getSourceMap()) { CLIUtils.writeFile(outputSourceMapPath, obfuscationResult.getSourceMap()); } } diff --git a/src/interfaces/IObfuscatorOptions.d.ts b/src/interfaces/IObfuscatorOptions.d.ts index 751100e8..58940d1a 100644 --- a/src/interfaces/IObfuscatorOptions.d.ts +++ b/src/interfaces/IObfuscatorOptions.d.ts @@ -11,6 +11,7 @@ export interface IObfuscatorOptions { selfDefending?: boolean; sourceMap?: boolean; sourceMapBaseUrl?: string; + sourceMapFileName?: string; sourceMapMode?: TSourceMapMode; unicodeArray?: boolean; unicodeArrayThreshold?: number; diff --git a/src/interfaces/IOptions.d.ts b/src/interfaces/IOptions.d.ts index 509af4db..3d7afb2f 100644 --- a/src/interfaces/IOptions.d.ts +++ b/src/interfaces/IOptions.d.ts @@ -11,6 +11,7 @@ export interface IOptions { readonly selfDefending: boolean; readonly sourceMap: boolean; readonly sourceMapBaseUrl: string; + readonly sourceMapFileName: string; readonly sourceMapMode: TSourceMapMode; readonly unicodeArray: boolean; readonly unicodeArrayThreshold: number; diff --git a/src/options/Options.ts b/src/options/Options.ts index 740cbd18..40b7ae65 100644 --- a/src/options/Options.ts +++ b/src/options/Options.ts @@ -97,7 +97,7 @@ export class Options implements IOptions { public readonly sourceMap: boolean; /** - * @type {boolean} + * @type {string} */ @IsString() @ValidateIf((options: IOptions) => Boolean(options.sourceMapBaseUrl)) @@ -107,6 +107,12 @@ export class Options implements IOptions { }) public readonly sourceMapBaseUrl: string; + /** + * @type {string} + */ + @IsString() + public readonly sourceMapFileName: string; + /** * @type {TSourceMapMode} */ diff --git a/src/options/OptionsNormalizer.ts b/src/options/OptionsNormalizer.ts index d4f4e0fc..5891e4aa 100644 --- a/src/options/OptionsNormalizer.ts +++ b/src/options/OptionsNormalizer.ts @@ -42,6 +42,7 @@ export class OptionsNormalizer { OptionsNormalizer.unicodeArrayThresholdRule, OptionsNormalizer.encodeUnicodeLiteralsRule, OptionsNormalizer.sourceMapBaseUrl, + OptionsNormalizer.sourceMapFileName, OptionsNormalizer.selfDefendingRule ]; @@ -108,9 +109,29 @@ export class OptionsNormalizer { * @returns {IOptions} */ private static sourceMapBaseUrl (options: IOptions): IOptions { - if (options.sourceMapBaseUrl) { + let sourceMapBaseUrl: string = options.sourceMapBaseUrl; + + if (sourceMapBaseUrl && !sourceMapBaseUrl.endsWith('/')) { Object.assign(options, { - sourceMapBaseUrl: Utils.normalizeUrl(options.sourceMapBaseUrl) + sourceMapBaseUrl: `${sourceMapBaseUrl}/` + }); + } + + return options; + } + + /** + * @param options + * @returns {IOptions} + */ + private static sourceMapFileName (options: IOptions): IOptions { + let sourceMapFileName: string = options.sourceMapFileName; + + if (sourceMapFileName) { + sourceMapFileName = sourceMapFileName.split('.')[0]; + + Object.assign(options, { + sourceMapFileName: `${sourceMapFileName}.js.map` }); } diff --git a/src/preset-options/DefaultPreset.ts b/src/preset-options/DefaultPreset.ts index d6427ba7..fd1f97c8 100644 --- a/src/preset-options/DefaultPreset.ts +++ b/src/preset-options/DefaultPreset.ts @@ -14,6 +14,7 @@ export const DEFAULT_PRESET: IObfuscatorOptions = Object.freeze({ selfDefending: true, sourceMap: false, sourceMapBaseUrl: '', + sourceMapFileName: '', sourceMapMode: SourceMapMode.Separate, unicodeArray: true, unicodeArrayThreshold: 0.8, diff --git a/src/preset-options/NoCustomNodesPreset.ts b/src/preset-options/NoCustomNodesPreset.ts index 4cf59083..faac40bc 100644 --- a/src/preset-options/NoCustomNodesPreset.ts +++ b/src/preset-options/NoCustomNodesPreset.ts @@ -14,6 +14,7 @@ export const NO_CUSTOM_NODES_PRESET: IObfuscatorOptions = Object.freeze({ selfDefending: false, sourceMap: false, sourceMapBaseUrl: '', + sourceMapFileName: '', sourceMapMode: SourceMapMode.Separate, unicodeArray: false, unicodeArrayThreshold: 0, diff --git a/test/functional-tests/JavaScriptObfuscator.spec.ts b/test/functional-tests/JavaScriptObfuscator.spec.ts index e0c5a697..ea8bd591 100644 --- a/test/functional-tests/JavaScriptObfuscator.spec.ts +++ b/test/functional-tests/JavaScriptObfuscator.spec.ts @@ -33,7 +33,7 @@ describe('JavaScriptObfuscator', () => { assert.isOk(JSON.parse(obfuscationResult.getSourceMap()).mappings); }); - it('should returns object with obfuscated code with inline source map and empty `sourceMap` if `sourceMapMode` is `inline', () => { + it('should returns object with obfuscated code with inline source map as Base64 string', () => { let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate( `var test = 1;`, Object.assign({}, NO_CUSTOM_NODES_PRESET, { @@ -47,7 +47,7 @@ describe('JavaScriptObfuscator', () => { obfuscationResult.getObfuscatedCode(), /sourceMappingURL=data:application\/json;base64/ ); - assert.isNotOk(obfuscationResult.getSourceMap()); + assert.isOk(obfuscationResult.getSourceMap()); }); it('should returns object with empty obfuscated code and source map with empty data if source code is empty', () => { diff --git a/test/functional-tests/JavaScriptObfuscatorCLI.spec.ts b/test/functional-tests/JavaScriptObfuscatorCLI.spec.ts index 19ef7707..b532f5bb 100644 --- a/test/functional-tests/JavaScriptObfuscatorCLI.spec.ts +++ b/test/functional-tests/JavaScriptObfuscatorCLI.spec.ts @@ -87,61 +87,125 @@ describe('JavaScriptObfuscatorCLI', function (): void { describe('--sourceMap option is set', () => { let outputSourceMapPath: string = `${outputFilePath}.map`; - it('should creates file with source map in the same directory as output file', () => { - JavaScriptObfuscator.runCLI([ - 'node', - 'javascript-obfuscator', - fixtureFilePath, - '--output', - outputFilePath, - '--compact', - 'true', - '--selfDefending', - '0', - '--sourceMap', - 'true' - ]); + describe('--sourceMapMode option is `separate`', () => { + it('should creates file with source map in the same directory as output file', () => { + JavaScriptObfuscator.runCLI([ + 'node', + 'javascript-obfuscator', + fixtureFilePath, + '--output', + outputFilePath, + '--compact', + 'true', + '--selfDefending', + '0', + '--sourceMap', + 'true' + ]); - assert.equal(fs.existsSync(outputSourceMapPath), true); + assert.equal(fs.existsSync(outputSourceMapPath), true); - const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }), - sourceMap: any = JSON.parse(content); + const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }), + sourceMap: any = JSON.parse(content); - assert.property(sourceMap, 'version'); - assert.property(sourceMap, 'sources'); - assert.property(sourceMap, 'names'); + assert.property(sourceMap, 'version'); + assert.property(sourceMap, 'sources'); + assert.property(sourceMap, 'names'); + }); + + it('should creates file with source map in the same directory as output file if `sourceMapBaseUrl` is set', () => { + JavaScriptObfuscator.runCLI([ + 'node', + 'javascript-obfuscator', + fixtureFilePath, + '--output', + outputFilePath, + '--compact', + 'true', + '--selfDefending', + '0', + '--sourceMap', + 'true', + '--sourceMapBaseUrl', + 'http://localhost:9000/' + ]); + + assert.equal(fs.existsSync(outputSourceMapPath), true); + + const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }), + sourceMap: any = JSON.parse(content); + + assert.property(sourceMap, 'version'); + assert.property(sourceMap, 'sources'); + assert.property(sourceMap, 'names'); + }); + + afterEach(() => { + fs.unlinkSync(outputSourceMapPath); + }); }); - it('should creates file with source map in the same directory as output file if `sourceMapBaseUrl` is set', () => { - JavaScriptObfuscator.runCLI([ - 'node', - 'javascript-obfuscator', - fixtureFilePath, - '--output', - outputFilePath, - '--compact', - 'true', - '--selfDefending', - '0', - '--sourceMap', - 'true', - '--sourceMapBaseUrl', - 'http://localhost:9000/' - ]); + describe('--sourceMapFileName option is set', () => { + let sourceMapFileName: string = 'test', + sourceMapFilePath: string = `${sourceMapFileName}.js.map`, + outputSourceMapFilePath: string = `${outputDirName}/${sourceMapFilePath}`; - assert.equal(fs.existsSync(outputSourceMapPath), true); + it('should creates source map file with given name in the same directory as output file', () => { + JavaScriptObfuscator.runCLI([ + 'node', + 'javascript-obfuscator', + fixtureFilePath, + '--output', + outputFilePath, + '--compact', + 'true', + '--selfDefending', + '0', + '--sourceMap', + 'true', + '--sourceMapFileName', + sourceMapFileName + ]); - const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' }), - sourceMap: any = JSON.parse(content); + assert.equal(fs.existsSync(outputSourceMapFilePath), true); - assert.property(sourceMap, 'version'); - assert.property(sourceMap, 'sources'); - assert.property(sourceMap, 'names'); + const content: string = fs.readFileSync(outputSourceMapFilePath, { encoding: 'utf8' }), + sourceMap: any = JSON.parse(content); + + assert.property(sourceMap, 'version'); + assert.property(sourceMap, 'sources'); + assert.property(sourceMap, 'names'); + }); + + afterEach(() => { + fs.unlinkSync(outputSourceMapFilePath); + }); + }); + + describe('--sourceMapMode option is `inline`', () => { + it('shouldn\'t create file with source map if `sourceMapMode` is `inline`', () => { + JavaScriptObfuscator.runCLI([ + 'node', + 'javascript-obfuscator', + fixtureFilePath, + '--output', + outputFilePath, + '--compact', + 'true', + '--selfDefending', + '0', + '--sourceMap', + 'true', + '--sourceMapMode', + 'inline' + ]); + + assert.equal(fs.existsSync(outputSourceMapPath), false); + }); }); afterEach(() => { fs.unlinkSync(outputFilePath); - fs.unlinkSync(outputSourceMapPath); }); }); diff --git a/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts b/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts index e367df2b..c829ac37 100644 --- a/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts +++ b/test/functional-tests/JavaScriptObfuscatorInternal.spec.ts @@ -10,18 +10,18 @@ describe('JavaScriptObfuscatorInternal', () => { describe(`setSourceMapUrl (url: string)`, () => { let javaScriptObfuscator: JavaScriptObfuscatorInternal, obfuscationResult: IObfuscationResult, - sourceMapUrl: string = 'test.map.js'; + sourceMapUrl: string = 'test.js.map'; it('should link obfuscated code with source map', () => { javaScriptObfuscator = new JavaScriptObfuscatorInternal( `var test = 1;`, Object.assign({}, NO_CUSTOM_NODES_PRESET, { - sourceMap: true + sourceMap: true, + sourceMapFileName: sourceMapUrl }) ); javaScriptObfuscator.obfuscate(); - javaScriptObfuscator.setSourceMapUrl(sourceMapUrl); obfuscationResult = javaScriptObfuscator.getObfuscationResult(); @@ -39,12 +39,12 @@ describe('JavaScriptObfuscatorInternal', () => { `var test = 1;`, Object.assign({}, NO_CUSTOM_NODES_PRESET, { sourceMap: true, - sourceMapBaseUrl: sourceMapBaseUrl + sourceMapBaseUrl: sourceMapBaseUrl, + sourceMapFileName: sourceMapUrl }) ); javaScriptObfuscator.obfuscate(); - javaScriptObfuscator.setSourceMapUrl(sourceMapUrl); obfuscationResult = javaScriptObfuscator.getObfuscationResult(); diff --git a/test/unit-tests/OptionsNormalizer.spec.ts b/test/unit-tests/OptionsNormalizer.spec.ts index fd9d22d3..d1ab308d 100644 --- a/test/unit-tests/OptionsNormalizer.spec.ts +++ b/test/unit-tests/OptionsNormalizer.spec.ts @@ -31,12 +31,14 @@ describe('OptionsNormalizer', () => { optionsPreset2 = Object.assign({}, DEFAULT_PRESET, { rotateUnicodeArray: true, sourceMapBaseUrl: 'http://localhost:9000', + sourceMapFileName: 'outputSourceMapName', unicodeArray: true, unicodeArrayThreshold: 0, wrapUnicodeArrayCalls: true }); optionsPreset3 = Object.assign({}, DEFAULT_PRESET, { domainLock: ['//localhost:9000', 'https://google.ru/abc?cde=fgh'], + sourceMapFileName: 'outputSourceMapName.map', unicodeArray: true, encodeUnicodeLiterals: true, wrapUnicodeArrayCalls: false @@ -52,12 +54,14 @@ describe('OptionsNormalizer', () => { expectedOptionsPreset2 = Object.assign({}, DEFAULT_PRESET, { rotateUnicodeArray: false, sourceMapBaseUrl: 'http://localhost:9000/', + sourceMapFileName: 'outputSourceMapName.js.map', unicodeArray: false, unicodeArrayThreshold: 0, wrapUnicodeArrayCalls: false }); expectedOptionsPreset3 = Object.assign({}, DEFAULT_PRESET, { domainLock: ['localhost', 'google.ru'], + sourceMapFileName: 'outputSourceMapName.js.map', unicodeArray: true, encodeUnicodeLiterals: true, wrapUnicodeArrayCalls: true diff --git a/test/unit-tests/SourceMapCorrector.spec.ts b/test/unit-tests/SourceMapCorrector.spec.ts index 7fee8dd0..6ee98be0 100644 --- a/test/unit-tests/SourceMapCorrector.spec.ts +++ b/test/unit-tests/SourceMapCorrector.spec.ts @@ -57,10 +57,6 @@ describe('SourceMapCorrector', () => { it('should add source map to obfuscated code as base64 encoded string', () => { assert.match(expectedObfuscationResult.getObfuscatedCode(), /data:application\/json;base64/); }); - - it('should clear original source map', () => { - assert.equal(expectedObfuscationResult.getSourceMap(), ''); - }); }); it('should add source map import to obfuscated code if source map mode is `separate`', () => { diff --git a/test/unit-tests/Utils.spec.ts b/test/unit-tests/Utils.spec.ts index 6650ba0a..43cdb53e 100644 --- a/test/unit-tests/Utils.spec.ts +++ b/test/unit-tests/Utils.spec.ts @@ -75,12 +75,6 @@ describe('Utils', () => { }); }); - describe('normalizeUrl (url: string): string', () => { - it('should normalize given url', () => { - assert.equal(Utils.normalizeUrl('http://localhost:9000'), 'http://localhost:9000/'); - }); - }); - describe('stringToJSFuck (string: string): string', () => { let expected: string = `${JSFuck.s} + ${JSFuck.t} + ${JSFuck.r} + ${JSFuck.i} + ${JSFuck.n} + ${JSFuck.g}`;