Skip to content

Commit

Permalink
fix(type-utils): prevent stack overflow in isTypeReadonly (#5860)
Browse files Browse the repository at this point in the history
fix(eslint-plugin): isTypeReadonly stack overflow (#4476)

Co-authored-by: Josh Goldberg <git@joshuakgoldberg.com>
  • Loading branch information
sviat9440 and JoshuaKGoldberg committed Oct 24, 2022
1 parent e70a10a commit a6d8f7e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
Expand Up @@ -5,6 +5,7 @@ import type {
InferMessageIdsTypeFromRule,
InferOptionsTypeFromRule,
} from '../../src/util';
import { readonlynessOptionsDefaults } from '../../src/util';
import { getFixturesRootDir, noFormat, RuleTester } from '../RuleTester';

type MessageIds = InferMessageIdsTypeFromRule<typeof rule>;
Expand Down Expand Up @@ -362,6 +363,23 @@ ruleTester.run('prefer-readonly-parameter-types', rule, {
},
],
},
{
name: 'circular readonly types (Bug: #4476)',
code: `
interface Obj {
readonly [K: string]: Obj;
}
function foo(event: Obj): void {}
`,
options: [
{
checkParameterProperties: true,
ignoreInferredTypes: false,
...readonlynessOptionsDefaults,
},
],
},
],
invalid: [
// arrays
Expand Down
4 changes: 4 additions & 0 deletions packages/type-utils/src/isTypeReadonly.ts
Expand Up @@ -113,6 +113,10 @@ function isTypeReadonlyObject(
return Readonlyness.Mutable;
}

if (indexInfo.type === type) {
return Readonlyness.Readonly;
}

return isTypeReadonlyRecurser(
checker,
indexInfo.type,
Expand Down
14 changes: 14 additions & 0 deletions packages/type-utils/tests/isTypeReadonly.test.ts
Expand Up @@ -134,6 +134,13 @@ describe('isTypeReadonly', () => {
);
});

describe('is readonly circular', () => {
const runTests = runTestIsReadonly;

it('handles circular readonly PropertySignature inside a readonly IndexSignature', () =>
runTests('interface Test { readonly [key: string]: Test };'));
});

describe('is not readonly', () => {
const runTests = runTestIsNotReadonly;

Expand All @@ -145,6 +152,13 @@ describe('isTypeReadonly', () => {
runTests,
);
});

describe('is not readonly circular', () => {
const runTests = runTestIsNotReadonly;

it('handles circular mutable PropertySignature inside a readonly IndexSignature', () =>
runTests('interface Test { [key: string]: Test };'));
});
});

describe('Union', () => {
Expand Down

0 comments on commit a6d8f7e

Please sign in to comment.