Internal fields of TIdentifierNamesCache now are optional. Fixed option validation and added normalization.

This commit is contained in:
sanex
2021-05-31 13:18:28 +03:00
parent 1f044e937d
commit c89ba21cba
9 changed files with 217 additions and 9 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -9,6 +9,7 @@ import { ControlFlowFlatteningThresholdRule } from './normalizer-rules/ControlFl
import { DeadCodeInjectionRule } from './normalizer-rules/DeadCodeInjectionRule';
import { DeadCodeInjectionThresholdRule } from './normalizer-rules/DeadCodeInjectionThresholdRule';
import { DomainLockRule } from './normalizer-rules/DomainLockRule';
import { IdentifierNamesCacheRule } from './normalizer-rules/IdentifierNamesCacheRule';
import { InputFileNameRule } from './normalizer-rules/InputFileNameRule';
import { SeedRule } from './normalizer-rules/SeedRule';
import { SelfDefendingRule } from './normalizer-rules/SelfDefendingRule';
@@ -29,6 +30,7 @@ export class OptionsNormalizer implements IOptionsNormalizer {
DeadCodeInjectionRule,
DeadCodeInjectionThresholdRule,
DomainLockRule,
IdentifierNamesCacheRule,
InputFileNameRule,
SeedRule,
SelfDefendingRule,
@@ -0,0 +1,32 @@
import { TOptionsNormalizerRule } from '../../types/options/TOptionsNormalizerRule';
import { IOptions } from '../../interfaces/options/IOptions';
/**
* @param {IOptions} options
* @returns {IOptions}
*/
export const IdentifierNamesCacheRule: TOptionsNormalizerRule = (options: IOptions): IOptions => {
let identifierNamesCache = options.identifierNamesCache;
if (identifierNamesCache && !identifierNamesCache.globalIdentifiers) {
identifierNamesCache = {
...identifierNamesCache,
globalIdentifiers: {}
};
}
if (identifierNamesCache && !identifierNamesCache.propertyIdentifiers) {
identifierNamesCache = {
...identifierNamesCache,
propertyIdentifiers: {}
};
}
options = {
...options,
identifierNamesCache
};
return options;
};
@@ -13,11 +13,11 @@ import { DEFAULT_PRESET } from '../presets/Default';
* @returns {boolean}
*/
const validateDictionary = (value: unknown | TIdentifierNamesCacheDictionary): boolean => {
if (typeof value !== 'object') {
return false;
if (value === undefined) {
return true;
}
if (value === null) {
if (typeof value !== 'object' || value === null) {
return false;
}
+2 -2
View File
@@ -1,7 +1,7 @@
import { TIdentifierNamesCacheDictionary } from './TIdentifierNamesCacheDictionary';
export type TIdentifierNamesCache = {
globalIdentifiers: TIdentifierNamesCacheDictionary;
propertyIdentifiers: TIdentifierNamesCacheDictionary;
globalIdentifiers?: TIdentifierNamesCacheDictionary;
propertyIdentifiers?: TIdentifierNamesCacheDictionary;
} | null;
@@ -257,6 +257,140 @@ describe('OptionsNormalizer', () => {
});
});
describe('identifierNamesCacheRule', () => {
describe('Variant #1: all fields are exist with values', () => {
before(() => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
},
propertyIdentifiers: {
bar: '_0x654321'
}
}
});
expectedOptionsPreset = {
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
},
propertyIdentifiers: {
bar: '_0x654321'
}
}
};
});
it('should not normalize options preset', () => {
assert.deepEqual(optionsPreset, expectedOptionsPreset);
});
});
describe('Variant #2: some fields are exist with values', () => {
before(() => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
},
propertyIdentifiers: {}
}
});
expectedOptionsPreset = {
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
},
propertyIdentifiers: {}
}
};
});
it('should not normalize options preset', () => {
assert.deepEqual(optionsPreset, expectedOptionsPreset);
});
});
describe('Variant #3: all fields are exist with empty objects', () => {
before(() => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {},
propertyIdentifiers: {}
}
});
expectedOptionsPreset = {
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {},
propertyIdentifiers: {}
}
};
});
it('should not normalize options preset', () => {
assert.deepEqual(optionsPreset, expectedOptionsPreset);
});
});
describe('Variant #4: some fields are missing', () => {
before(() => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
}
}
});
expectedOptionsPreset = {
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
},
propertyIdentifiers: {}
}
};
});
it('should normalize options preset', () => {
assert.deepEqual(optionsPreset, expectedOptionsPreset);
});
});
describe('Variant #5: all fields are missing', () => {
before(() => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
identifierNamesCache: {}
});
expectedOptionsPreset = {
...getDefaultOptions(),
identifierNamesCache: {
globalIdentifiers: {},
propertyIdentifiers: {}
}
};
});
it('should normalize options preset', () => {
assert.deepEqual(optionsPreset, expectedOptionsPreset);
});
});
});
describe('seedRule', () => {
describe('Variant #1: seed value is string', () => {
before(() => {
@@ -76,7 +76,47 @@ describe('`identifierNamesCache` validation', () => {
});
});
describe('Variant #4: `null` value', () => {
describe('Variant #4: object with some empty identifier names cache', () => {
let testFunc: () => string;
beforeEach(() => {
testFunc = () => JavaScriptObfuscator.obfuscate(
'',
{
...NO_ADDITIONAL_NODES_PRESET,
identifierNamesCache: {
globalIdentifiers: {
foo: '_0x123456'
}
}
}
).getObfuscatedCode();
});
it('should pass validation', () => {
assert.doesNotThrow(testFunc);
});
});
describe('Variant #5: empty object', () => {
let testFunc: () => string;
beforeEach(() => {
testFunc = () => JavaScriptObfuscator.obfuscate(
'',
{
...NO_ADDITIONAL_NODES_PRESET,
identifierNamesCache: {}
}
).getObfuscatedCode();
});
it('should pass validation', () => {
assert.doesNotThrow(testFunc);
});
});
describe('Variant #5: `null` value', () => {
let testFunc: () => string;
beforeEach(() => {