mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Merge pull request #740 from javascript-obfuscator/string-array-calls-wrapper-mangled-generator-fix
Fixed `stringArrayCallsWrapper` option with `mangled` names generator
This commit is contained in:
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+2
-2
@@ -57,7 +57,7 @@
|
||||
"@types/mkdirp": "1.0.1",
|
||||
"@types/mocha": "8.0.3",
|
||||
"@types/multimatch": "4.0.0",
|
||||
"@types/node": "14.6.4",
|
||||
"@types/node": "14.10.0",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/sinon": "9.0.5",
|
||||
"@types/string-template": "1.0.2",
|
||||
@@ -69,7 +69,7 @@
|
||||
"coveralls": "3.1.0",
|
||||
"eslint": "7.8.1",
|
||||
"eslint-plugin-import": "2.22.0",
|
||||
"eslint-plugin-jsdoc": "30.3.3",
|
||||
"eslint-plugin-jsdoc": "30.4.0",
|
||||
"eslint-plugin-no-null": "1.0.2",
|
||||
"eslint-plugin-prefer-arrow": "1.2.2",
|
||||
"eslint-plugin-unicorn": "21.0.0",
|
||||
|
||||
@@ -60,14 +60,68 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
|
||||
}
|
||||
|
||||
/**
|
||||
* We can only ignore limited nameLength, it has no sense here
|
||||
* @param {string} nextName
|
||||
* @param {string} prevName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isIncrementedMangledName (nextName: string, prevName: string): boolean {
|
||||
if (nextName === prevName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nextNameLength: number = nextName.length;
|
||||
const prevNameLength: number = prevName.length;
|
||||
|
||||
if (nextNameLength !== prevNameLength) {
|
||||
return nextNameLength > prevNameLength;
|
||||
}
|
||||
|
||||
for (let i: number = 0; i < nextNameLength; i++) {
|
||||
const nextNameCharacter: string = nextName[i];
|
||||
const prevNameCharacter: string = prevName[i];
|
||||
|
||||
if (nextNameCharacter === prevNameCharacter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isUpperCaseNextNameCharacter: boolean = MangledIdentifierNamesGenerator.isUpperCaseCharacter(nextNameCharacter);
|
||||
const isUpperCasePrevNameCharacter: boolean = MangledIdentifierNamesGenerator.isUpperCaseCharacter(prevNameCharacter);
|
||||
|
||||
if (
|
||||
isUpperCaseNextNameCharacter
|
||||
&& !isUpperCasePrevNameCharacter
|
||||
) {
|
||||
return true;
|
||||
} else if (
|
||||
!isUpperCaseNextNameCharacter
|
||||
&& isUpperCasePrevNameCharacter
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return nextName > prevName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} character
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private static isUpperCaseCharacter (string: string): boolean {
|
||||
return /^[A-Z]*$/.test(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates next name based on a global previous mangled name
|
||||
* We can ignore nameLength parameter here, it hasn't sense with this generator
|
||||
*
|
||||
* @param {number} nameLength
|
||||
* @returns {string}
|
||||
*/
|
||||
public generateNext (nameLength?: number): string {
|
||||
const identifierName: string = this.generateNewMangledName(this.previousMangledName);
|
||||
|
||||
this.previousMangledName = identifierName;
|
||||
this.updatePreviousMangledName(identifierName);
|
||||
this.preserveName(identifierName);
|
||||
|
||||
return identifierName;
|
||||
@@ -84,7 +138,7 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
|
||||
const identifierName: string = this.generateNewMangledName(this.previousMangledName);
|
||||
const identifierNameWithPrefix: string = `${prefix}${identifierName}`;
|
||||
|
||||
this.previousMangledName = identifierName;
|
||||
this.updatePreviousMangledName(identifierName);
|
||||
|
||||
if (!this.isValidIdentifierName(identifierNameWithPrefix)) {
|
||||
return this.generateForGlobalScope(nameLength);
|
||||
@@ -116,6 +170,7 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
|
||||
|
||||
MangledIdentifierNamesGenerator.lastMangledNameInScopeMap.set(lexicalScopeNode, identifierName);
|
||||
|
||||
this.updatePreviousMangledName(identifierName);
|
||||
this.preserveNameForLexicalScope(identifierName, lexicalScopeNode);
|
||||
|
||||
return identifierName;
|
||||
@@ -137,6 +192,17 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
|
||||
return MangledIdentifierNamesGenerator.nameSequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
protected updatePreviousMangledName (name: string): void {
|
||||
if (!MangledIdentifierNamesGenerator.isIncrementedMangledName(name, this.previousMangledName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.previousMangledName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} previousMangledName
|
||||
* @returns {string}
|
||||
|
||||
@@ -268,7 +268,7 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
|
||||
const isFilledScopeCallsWrapperNamesList: boolean = stringArrayScopeCallsWrapperNames.length === this.options.stringArrayWrappersCount;
|
||||
|
||||
if (!isFilledScopeCallsWrapperNamesList) {
|
||||
const nextScopeCallsWrapperName: string = this.identifierNamesGenerator.generateForLexicalScope(currentLexicalScopeNode);
|
||||
const nextScopeCallsWrapperName: string = this.identifierNamesGenerator.generateNext();
|
||||
|
||||
stringArrayScopeCallsWrapperNames.push(nextScopeCallsWrapperName);
|
||||
stringArrayScopeCallsWrapperDataByEncoding[encoding] = {
|
||||
|
||||
+28
-10
@@ -1,28 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
|
||||
import { IdentifierNamesGenerator } from '../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
|
||||
|
||||
(function () {
|
||||
const JavaScriptObfuscator: any = require('../../index');
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
const foo = 'foo';
|
||||
const bar = 'bar';
|
||||
const foo = 'aaa';
|
||||
|
||||
function test (a, b) {
|
||||
const bar = 'bbb';
|
||||
|
||||
function test1 (a, b) {
|
||||
const baz = 'ccc';
|
||||
|
||||
function test () {
|
||||
const baz = 'baz';
|
||||
const bark = 'bark';
|
||||
|
||||
function test1() {
|
||||
const hawk = 'hawk';
|
||||
const eagle = 'eagle';
|
||||
}
|
||||
function test2 (a, b) {
|
||||
const bark = 'ddd';
|
||||
|
||||
return bark;
|
||||
}
|
||||
|
||||
return baz + test2();
|
||||
}
|
||||
|
||||
return bar + test1();
|
||||
}
|
||||
|
||||
function test3 (a, b) {
|
||||
const hawk = 'eee';
|
||||
|
||||
return hawk;
|
||||
}
|
||||
|
||||
foo + test() + test3();
|
||||
`,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
compact: false,
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
renameGlobals: true,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
|
||||
+194
-21
@@ -256,41 +256,214 @@ describe('StringArrayTransformer', function () {
|
||||
});
|
||||
|
||||
describe('Variant #5: `stringArrayWrappersChainedCalls` option is enabled', () => {
|
||||
describe('Variant #1: correct evaluation of the string array wrappers chained calls', () => {
|
||||
const samplesCount: number = 50;
|
||||
const expectedEvaluationResult: string = 'aaabbbcccdddeee';
|
||||
let isEvaluationSuccessful: boolean = true;
|
||||
describe('Variant #1: correct chained calls', () => {
|
||||
describe('Variant #1: `Mangled` identifier names generator', () => {
|
||||
const stringArrayCallRegExp: RegExp = new RegExp(
|
||||
'const q *= *b;' +
|
||||
'const foo *= *q\\(\'0x0\'\\);' +
|
||||
'function test\\(c, *d\\) *{' +
|
||||
'const r *= *q;' +
|
||||
'const e *= *r\\(\'0x1\'\\);' +
|
||||
'const f *= *r\\(\'0x2\'\\);' +
|
||||
'function g\\(h, *i\\) *{' +
|
||||
'const s *= *r;' +
|
||||
'const j *= *s\\(\'0x3\'\\);' +
|
||||
'const k *= *s\\(\'0x4\'\\);' +
|
||||
'function l\\(m, *n *\\) *{' +
|
||||
'const t *= *s;' +
|
||||
'const o *= *t\\(\'0x3\'\\);' +
|
||||
'const p *= *t\\(\'0x4\'\\);' +
|
||||
'return o *\\+ *p;' +
|
||||
'}' +
|
||||
'return j *\\+ *k;' +
|
||||
'}' +
|
||||
'return e *\\+ *f *\\+ *g\\(\\);' +
|
||||
'}'
|
||||
);
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/string-array-wrappers-chained-calls-eval.js');
|
||||
let obfuscatedCode: string;
|
||||
|
||||
for (let i = 0; i < samplesCount; i++) {
|
||||
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/string-array-wrappers-chained-calls-1.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None,
|
||||
StringArrayEncoding.Rc4
|
||||
],
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 5
|
||||
stringArrayWrappersCount: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
const evaluationResult: string = eval(obfuscatedCode);
|
||||
it('should add correct scope calls wrappers', () => {
|
||||
assert.match(obfuscatedCode, stringArrayCallRegExp);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (evaluationResult !== expectedEvaluationResult) {
|
||||
isEvaluationSuccessful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
describe('Variant #2: correct evaluation of the string array wrappers chained calls', () => {
|
||||
describe('Variant #1: base', () => {
|
||||
describe('Variant #1: `Hexadecimal` identifier names generator', () => {
|
||||
const samplesCount: number = 50;
|
||||
const expectedEvaluationResult: string = 'aaabbbcccdddeee';
|
||||
let isEvaluationSuccessful: boolean = true;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/string-array-wrappers-chained-calls-1.js');
|
||||
|
||||
for (let i = 0; i < samplesCount; i++) {
|
||||
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None,
|
||||
StringArrayEncoding.Rc4
|
||||
],
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 5
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
const evaluationResult: string = eval(obfuscatedCode);
|
||||
|
||||
if (evaluationResult !== expectedEvaluationResult) {
|
||||
isEvaluationSuccessful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should correctly evaluate string array wrappers chained calls', () => {
|
||||
assert.equal(isEvaluationSuccessful, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: `Mangled` identifier names generator', () => {
|
||||
const samplesCount: number = 50;
|
||||
const expectedEvaluationResult: string = 'aaabbbcccdddeee';
|
||||
let isEvaluationSuccessful: boolean = true;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/string-array-wrappers-chained-calls-1.js');
|
||||
|
||||
for (let i = 0; i < samplesCount; i++) {
|
||||
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None,
|
||||
StringArrayEncoding.Rc4
|
||||
],
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 5
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
const evaluationResult: string = eval(obfuscatedCode);
|
||||
|
||||
if (evaluationResult !== expectedEvaluationResult) {
|
||||
isEvaluationSuccessful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should correctly evaluate string array wrappers chained calls', () => {
|
||||
assert.equal(isEvaluationSuccessful, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly evaluate string array wrappers chained calls', () => {
|
||||
assert.equal(isEvaluationSuccessful, true);
|
||||
describe('Variant #2: advanced', () => {
|
||||
describe('Variant #1: `Hexadecimal` identifier names generator', () => {
|
||||
const samplesCount: number = 50;
|
||||
const expectedEvaluationResult: string = 'aaabbbcccdddeee';
|
||||
let isEvaluationSuccessful: boolean = true;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/string-array-wrappers-chained-calls-2.js');
|
||||
|
||||
for (let i = 0; i < samplesCount; i++) {
|
||||
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None,
|
||||
StringArrayEncoding.Rc4
|
||||
],
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 5
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
const evaluationResult: string = eval(obfuscatedCode);
|
||||
|
||||
if (evaluationResult !== expectedEvaluationResult) {
|
||||
isEvaluationSuccessful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should correctly evaluate string array wrappers chained calls', () => {
|
||||
assert.equal(isEvaluationSuccessful, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: `Mangled` identifier names generator', () => {
|
||||
const samplesCount: number = 50;
|
||||
const expectedEvaluationResult: string = 'aaabbbcccdddeee';
|
||||
let isEvaluationSuccessful: boolean = true;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/string-array-wrappers-chained-calls-2.js');
|
||||
|
||||
for (let i = 0; i < samplesCount; i++) {
|
||||
const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None,
|
||||
StringArrayEncoding.Rc4
|
||||
],
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 5
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
const evaluationResult: string = eval(obfuscatedCode);
|
||||
|
||||
if (evaluationResult !== expectedEvaluationResult) {
|
||||
isEvaluationSuccessful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should correctly evaluate string array wrappers chained calls', () => {
|
||||
assert.equal(isEvaluationSuccessful, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+9
-2
@@ -1,13 +1,20 @@
|
||||
const foo = 'aaa';
|
||||
|
||||
function test () {
|
||||
function test (a, b) {
|
||||
const bar = 'bbb';
|
||||
const baz = 'ccc';
|
||||
|
||||
function test1 () {
|
||||
function test1 (a, b) {
|
||||
const bark = 'ddd';
|
||||
const hawk = 'eee';
|
||||
|
||||
function test2 (a, b) {
|
||||
const bark = 'ddd';
|
||||
const hawk = 'eee';
|
||||
|
||||
return bark + hawk;
|
||||
}
|
||||
|
||||
return bark + hawk;
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
const foo = 'aaa';
|
||||
|
||||
function test (a, b) {
|
||||
const bar = 'bbb';
|
||||
|
||||
function test1 (a, b) {
|
||||
const baz = 'ccc';
|
||||
|
||||
function test2 (a, b) {
|
||||
const bark = 'ddd';
|
||||
|
||||
return bark;
|
||||
}
|
||||
|
||||
return baz + test2();
|
||||
}
|
||||
|
||||
return bar + test1();
|
||||
}
|
||||
|
||||
function test3 (a, b) {
|
||||
const hawk = 'eee';
|
||||
|
||||
return hawk;
|
||||
}
|
||||
|
||||
foo + test() + test3();
|
||||
+60
-1
@@ -10,6 +10,7 @@ import { IInversifyContainerFacade } from '../../../../src/interfaces/container/
|
||||
import { IdentifierNamesGenerator } from '../../../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
|
||||
|
||||
import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade';
|
||||
import { MangledIdentifierNamesGenerator } from '../../../../src/generators/identifier-names-generators/MangledIdentifierNamesGenerator';
|
||||
|
||||
describe('MangledIdentifierNamesGenerator', () => {
|
||||
describe('generateNext', () => {
|
||||
@@ -170,7 +171,65 @@ describe('MangledIdentifierNamesGenerator', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isValidIdentifierName (identifierName: string): boolean', () => {
|
||||
describe('isIncrementedMangledName', () => {
|
||||
const names: [nameA: string, nameB: string, result: boolean][] = [
|
||||
['aa', 'aa', false],
|
||||
|
||||
['a', '9', true],
|
||||
['9', 'a', false],
|
||||
|
||||
['b', 'a', true],
|
||||
['a', 'b', false],
|
||||
|
||||
['A', 'z', true],
|
||||
['z', 'A', false],
|
||||
|
||||
['B', 'A', true],
|
||||
['A', 'B', false],
|
||||
|
||||
['a0', 'Z', true],
|
||||
['Z', 'a0', false],
|
||||
|
||||
['a9', 'a0', true],
|
||||
['a0', 'a9', false],
|
||||
|
||||
['z0', 'a0', true],
|
||||
['a0', 'z0', false],
|
||||
|
||||
['a0', 'a', true],
|
||||
['a', 'a0', false],
|
||||
|
||||
['A0', 'a0', true],
|
||||
['a0', 'A0', false],
|
||||
|
||||
['z1', 'a0', true],
|
||||
['a0', 'z1', false],
|
||||
|
||||
['aa0', 'ZZ', true],
|
||||
['ZZ', 'aa0', false],
|
||||
|
||||
['aaA', 'aa0', true],
|
||||
['aa0', 'aaA', false]
|
||||
];
|
||||
|
||||
names.forEach(([nameA, nameB, expectedResult], index: number) => {
|
||||
describe(`Variant #${index + 1}: \`${nameA}\` and \`${nameB}\``, () => {
|
||||
let result: boolean;
|
||||
|
||||
beforeEach(() => {
|
||||
console.time();
|
||||
result = MangledIdentifierNamesGenerator.isIncrementedMangledName(nameA, nameB);
|
||||
console.timeEnd();
|
||||
});
|
||||
|
||||
it('should compare mangled names', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('isValidIdentifierName', () => {
|
||||
describe('Variant #1: reserved name as simple string', () => {
|
||||
const expectedFirstIdentifier: string = 'a';
|
||||
const expectedSecondIdentifier: string = 'd';
|
||||
|
||||
@@ -415,10 +415,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.3.tgz#6356df2647de9eac569f9a52eda3480fa9e70b4d"
|
||||
integrity sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA==
|
||||
|
||||
"@types/node@14.6.4":
|
||||
version "14.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
|
||||
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
|
||||
"@types/node@14.10.0":
|
||||
version "14.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.0.tgz#15815dff82c8dc30827f6b1286f865902945095a"
|
||||
integrity sha512-SOIyrdADB4cq6eY1F+9iU48iIomFAPltu11LCvA9PKcyEwHadjCFzNVPotAR+oEJA0bCP4Xvvgy+vwu1ZjVh8g==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.0"
|
||||
@@ -2035,10 +2035,10 @@ eslint-plugin-import@2.22.0:
|
||||
resolve "^1.17.0"
|
||||
tsconfig-paths "^3.9.0"
|
||||
|
||||
eslint-plugin-jsdoc@30.3.3:
|
||||
version "30.3.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.3.3.tgz#25ddf2e59164a6182c5a9e12e6560d69e252013d"
|
||||
integrity sha512-u2z0LUTm00KLrWB2h7y+hkzYcTIDIi87efXRnv36cFvs23hIOuT77FdZNDBxbB4dxquHBNsyxLpyEuERYUVNEA==
|
||||
eslint-plugin-jsdoc@30.4.0:
|
||||
version "30.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.4.0.tgz#3c84f59b6a04eaef2b636f75eeee905d16b7f2f9"
|
||||
integrity sha512-eb22QADWcISPQJwFJ+rUAl1NXdyOq3qy0Cp0+MZzpwlqFgJ+eJ7Fd/jYTfwDuN8QyFWumuyzSpwQBnF4PfM9Wg==
|
||||
dependencies:
|
||||
comment-parser "^0.7.6"
|
||||
debug "^4.1.1"
|
||||
|
||||
Reference in New Issue
Block a user