Selaa lähdekoodia

Fixed tests. Added `inputFileName` option validation

sanex 3 vuotta sitten
vanhempi
commit
4ab4406f5e

+ 1 - 0
CHANGELOG.md

@@ -3,6 +3,7 @@ Change Log
 v2.17.0
 ---
 * **New option**: `sourceMapSourcesMode` allows to control `sources` and `sourcesContent` fields of the source map
+* `inputFileName` option now required when using NodeJS API and `sourceMapSourcesMode` option has `sources` value`.
 * Fixed some cases with wrong source map file name generation when `sourceMapFileName` option is set
 
 v2.16.0

+ 2 - 1
README.md

@@ -842,6 +842,7 @@ Prevents obfuscation of `require` imports. Could be helpful in some cases when f
 Type: `string` Default: `''`
 
 Allows to set name of the input file with source code. This name will be used internally for source map generation.
+Required when using NodeJS API and `sourceMapSourcesMode` option has `sources` value`.
 
 ### `log`
 Type: `boolean` Default: `false`
@@ -1078,7 +1079,7 @@ Type: `string` Default: `sources-content`
 
 Allows to control `sources` and `sourcesContent` fields of the source map:
 * `sources-content` - adds dummy `sources` field, adds `sourcesContent` field with the original source code;
-* `sources` - adds `sources` field with a valid source description, does not add `sourcesContent` field.
+* `sources` - adds `sources` field with a valid source description, does not add `sourcesContent` field. When using NodeJS API it's required to define `inputFileName` option that will be used as `sources` field value.
 
 ### `splitStrings`
 Type: `boolean` Default: `false`

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/index.browser.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/index.cli.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/index.js


+ 1 - 1
src/JavaScriptObfuscator.ts

@@ -259,7 +259,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
                         sourceContent: sourceCode
                     }
                     : {
-                        sourceMap: this.options.inputFileName
+                        sourceMap: this.options.inputFileName || 'sourceMap'
                     }
             }
         };

+ 2 - 1
src/options/Options.ts

@@ -49,6 +49,7 @@ import { ValidationErrorsFormatter } from './ValidationErrorsFormatter';
 import { IsAllowedForObfuscationTargets } from './validators/IsAllowedForObfuscationTargets';
 import { IsDomainLockRedirectUrl } from './validators/IsDomainLockRedirectUrl';
 import { IsIdentifierNamesCache } from './validators/IsIdentifierNamesCache';
+import { IsInputFileName } from './validators/IsInputFileName';
 
 @injectable()
 export class Options implements IOptions {
@@ -195,7 +196,7 @@ export class Options implements IOptions {
     /**
      * @type {string}
      */
-    @IsString()
+    @IsInputFileName()
     public readonly inputFileName!: string;
 
     /**

+ 18 - 0
src/options/validators/IsInputFileName.ts

@@ -0,0 +1,18 @@
+import { IsNotEmpty, IsString, ValidateIf } from 'class-validator';
+
+import { TInputOptions } from '../../types/options/TInputOptions';
+
+import { SourceMapSourcesMode } from '../../enums/source-map/SourceMapSourcesMode';
+
+/**
+ * @returns {PropertyDecorator}
+ */
+export const IsInputFileName = (): PropertyDecorator => {
+    return (target: any, key: string | symbol): void => {
+        IsString()(target, key);
+        ValidateIf(({sourceMapSourcesMode}: TInputOptions) => {
+            return sourceMapSourcesMode === SourceMapSourcesMode.Sources;
+        })(target, key);
+        IsNotEmpty()(target, key);
+    };
+};

+ 123 - 0
test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts

@@ -12,6 +12,7 @@ import { IObfuscationResult } from '../../../src/interfaces/source-code/IObfusca
 import { ISourceMap } from '../../../src/interfaces/source-code/ISourceMap';
 
 import { SourceMapMode } from '../../../src/enums/source-map/SourceMapMode';
+import { SourceMapSourcesMode } from '../../../src/enums/source-map/SourceMapSourcesMode';
 import { StringArrayEncoding } from '../../../src/enums/node-transformers/string-array-transformers/StringArrayEncoding';
 import { StringArrayIndexesType } from '../../../src/enums/node-transformers/string-array-transformers/StringArrayIndexesType';
 import { StringArrayWrappersType } from '../../../src/enums/node-transformers/string-array-transformers/StringArrayWrappersType';
@@ -251,6 +252,128 @@ describe('JavaScriptObfuscator', () => {
                     assert.isNotOk(sourceMapMappings);
                 });
             });
+
+            describe('`sourceMapSourceMode` is set', () => {
+                describe('`sourcesContent` value', () => {
+                    let code: string,
+                        obfuscatedCode: string,
+                        sourceMap: ISourceMap,
+                        resolvedSources: string;
+
+                    beforeEach((done) => {
+                        code = readFileAsString(__dirname + '/fixtures/simple-input-1.js');
+                        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                sourceMap: true,
+                                sourceMapSourcesMode: SourceMapSourcesMode.SourcesContent
+                            }
+                        );
+
+                        obfuscatedCode = obfuscationResult.getObfuscatedCode();
+                        sourceMap = JSON.parse(obfuscationResult.getSourceMap());
+                        resolveSources(sourceMap, '/', fs.readFile, (error, result) => {
+                            resolvedSources = typeof result.sourcesContent[0] === 'string'
+                                ? result.sourcesContent[0]
+                                : '';
+                            done();
+                        });
+                    });
+
+                    it('should return correct obfuscated code', () => {
+                        assert.isOk(obfuscatedCode);
+                    });
+
+                    it('should return correct source map mappings', () => {
+                        assert.isOk(sourceMap.mappings);
+                    });
+
+                    it('should define `sources` field for source map', () => {
+                        assert.property(sourceMap, 'sources');
+                    });
+
+                    it('should define `sourcesContent` field for source map', () => {
+                        assert.property(sourceMap, 'sourcesContent');
+                    });
+
+                    it('should define placeholder `sources` field for source map', () => {
+                        assert.deepEqual(sourceMap.sources, ['sourceMap']);
+                    });
+
+                    it('should define `sourcesContent` value with source code', () => {
+                        assert.deepEqual(sourceMap.sourcesContent[0], code);
+                    });
+
+                    it('should resolve correct sources from source map', () => {
+                        assert.equal(resolvedSources, code);
+                    });
+                });
+
+                describe('`sources` value', () => {
+                    describe('`inputFileName` option is set', () => {
+                        let code: string,
+                            obfuscatedCode: string,
+                            sourceMap: ISourceMap;
+
+                        beforeEach(() => {
+                            code = readFileAsString(__dirname + '/fixtures/simple-input-1.js');
+                            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                                code,
+                                {
+                                    ...NO_ADDITIONAL_NODES_PRESET,
+                                    inputFileName: 'someFile.js',
+                                    sourceMap: true,
+                                    sourceMapSourcesMode: SourceMapSourcesMode.Sources
+                                }
+                            );
+
+                            obfuscatedCode = obfuscationResult.getObfuscatedCode();
+                            sourceMap = JSON.parse(obfuscationResult.getSourceMap());
+                        });
+
+                        it('should return correct obfuscated code', () => {
+                            assert.isOk(obfuscatedCode);
+                        });
+
+                        it('should return correct source map mappings', () => {
+                            assert.isOk(sourceMap.mappings);
+                        });
+
+                        it('should define `sources` field for source map', () => {
+                            assert.property(sourceMap, 'sources');
+                        });
+
+                        it('should not define `sourcesContent` field for source map', () => {
+                            assert.notProperty(sourceMap, 'sourcesContent');
+                        });
+
+                        it('should define placeholder `sources` field for source map', () => {
+                            assert.deepEqual(sourceMap.sources, ['someFile.js']);
+                        });
+                    })
+
+                    describe('`inputFileName` option is not set', () => {
+                        let testFunc: () => IObfuscationResult;
+
+                        beforeEach(() => {
+                            const code: string = readFileAsString(__dirname + '/fixtures/simple-input-1.js');
+                            testFunc = () => JavaScriptObfuscator.obfuscate(
+                                code,
+                                {
+                                    ...NO_ADDITIONAL_NODES_PRESET,
+                                    sourceMap: true,
+                                    sourceMapSourcesMode: SourceMapSourcesMode.Sources
+                                }
+                            );
+                        });
+
+                        it('should throw an error', () => {
+                            assert.throws(testFunc, Error);
+                        });
+                    });
+                });
+            });
         });
 
         describe('variable inside global scope', () => {

+ 72 - 0
test/functional-tests/options/input-file-name/Validation.spec.ts

@@ -0,0 +1,72 @@
+import { assert } from 'chai';
+
+import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscatorFacade';
+
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
+import { SourceMapSourcesMode } from '../../../../src/enums/source-map/SourceMapSourcesMode';
+
+describe('`inputFileName` validation', () => {
+    describe('IsInputFileName', () => {
+        describe('Variant #1: positive validation', () => {
+            describe('Variant #1: empty string when `sourceMapSourcesMode: \'sources-content\'', () => {
+                let testFunc: () => string;
+
+                beforeEach(() => {
+                    testFunc = () => JavaScriptObfuscator.obfuscate(
+                        '',
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            inputFileName: '',
+                            sourceMapSourcesMode: SourceMapSourcesMode.SourcesContent
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should pass validation', () => {
+                    assert.doesNotThrow(testFunc);
+                });
+            });
+
+            describe('Variant #2: string with input file name when `sourceMapSourcesMode: \'sources\'', () => {
+                let testFunc: () => string;
+
+                beforeEach(() => {
+                    testFunc = () => JavaScriptObfuscator.obfuscate(
+                        '',
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            inputFileName: 'some-file.js',
+                            sourceMapSourcesMode: SourceMapSourcesMode.Sources
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should pass validation', () => {
+                    assert.doesNotThrow(testFunc);
+                });
+            });
+        });
+
+        describe('Variant #2: negative validation', () => {
+            describe('Variant #1: empty string when `sourceMapSourcesMode: \'sources\'', () => {
+                const expectedError: string = 'should not be empty';
+                let testFunc: () => string;
+
+                beforeEach(() => {
+                    testFunc = () => JavaScriptObfuscator.obfuscate(
+                        '',
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            inputFileName: '',
+                            sourceMapSourcesMode: SourceMapSourcesMode.Sources
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should not pass validation', () => {
+                    assert.throws(testFunc, expectedError);
+                });
+            });
+        });
+    });
+});

+ 7 - 0
test/helpers/atob.ts

@@ -0,0 +1,7 @@
+/**
+ * @param {string} encodedString
+ * @returns {string}
+ */
+export function atob (encodedString: string): string {
+    return Buffer.from(encodedString, 'base64').toString();
+}

+ 0 - 15
test/helpers/cryptUtilsAtob.ts

@@ -1,15 +0,0 @@
-/**
- * @param {string} encodedString
- * @returns {string}
- */
-export function cryptUtilsAtob (encodedString: string): string {
-    const baseDecodedString = atob(encodedString);
-
-    var tempDecodedString = '';
-
-    for (let k = 0, length = baseDecodedString.length; k < length; k++) {
-        tempDecodedString += '%' + ('00' + baseDecodedString.charCodeAt(k).toString(16)).slice(-2);
-    }
-
-    return decodeURIComponent(tempDecodedString);
-}

+ 2 - 2
test/helpers/parseSourceMapFromObfuscatedCode.ts

@@ -1,11 +1,11 @@
 import { ISourceMap } from '../../src/interfaces/source-code/ISourceMap';
 
-import { cryptUtilsAtob } from './cryptUtilsAtob';
+import { atob } from './atob';
 
 /**
  * @param {string} obfuscatedCodeWithInlineSourceMap
  * @returns {ISourceMap}
  */
 export function parseSourceMapFromObfuscatedCode (obfuscatedCodeWithInlineSourceMap: string): ISourceMap {
-    return JSON.parse(cryptUtilsAtob(obfuscatedCodeWithInlineSourceMap.split('base64,')[1]));
+    return JSON.parse(atob(obfuscatedCodeWithInlineSourceMap.split('base64,')[1]));
 }

+ 1 - 0
test/index.spec.ts

@@ -136,6 +136,7 @@ import './functional-tests/options/OptionsNormalizer.spec';
 import './functional-tests/options/domain-lock-destination/Validation.spec';
 import './functional-tests/options/domain-lock/Validation.spec';
 import './functional-tests/options/identifier-names-cache/Validation.spec';
+import './functional-tests/options/input-file-name/Validation.spec';
 import './functional-tests/storages/string-array-transformers/string-array-storage/StringArrayStorage.spec';
 
 /**

+ 4 - 4
test/unit-tests/utils/CryptUtils.spec.ts

@@ -8,7 +8,7 @@ import { ICryptUtils } from '../../../src/interfaces/utils/ICryptUtils';
 import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
 
 import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
-import { cryptUtilsAtob } from '../../helpers/cryptUtilsAtob';
+import { atob } from '../../helpers/atob';
 
 describe('CryptUtils', () => {
     let cryptUtils: ICryptUtils;
@@ -30,7 +30,7 @@ describe('CryptUtils', () => {
 
            before(() => {
                encodedString = cryptUtils.btoa('string');
-               decodedString = cryptUtilsAtob(encodedString);
+               decodedString = atob(encodedString);
            });
 
            it('should create a base-64 encoded string from a given string', () => {
@@ -51,7 +51,7 @@ describe('CryptUtils', () => {
 
             before(() => {
                 encodedString = cryptUtils.btoa('stri');
-                decodedString = cryptUtilsAtob(encodedString);
+                decodedString = atob(encodedString);
             });
 
             it('should create a base-64 encoded string from a given string with padding characters', () => {
@@ -72,7 +72,7 @@ describe('CryptUtils', () => {
 
             before(() => {
                 encodedString = cryptUtils.btoa('тест');
-                decodedString = cryptUtilsAtob(encodedString);
+                decodedString = atob(encodedString);
             });
 
             it('should create a base-64 encoded string from a given string', () => {

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä