From c924f434e1357fae32d361db1a56255d198a1051 Mon Sep 17 00:00:00 2001 From: Svyatoslav Zaytsev Date: Sun, 23 Oct 2022 22:19:24 +0300 Subject: [PATCH] fix(eslint-plugin): isTypeReadonly stack overflow (#4476) --- .../prefer-readonly-parameter-types.test.ts | 19 +++++++++++++++++++ packages/type-utils/src/isTypeReadonly.ts | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/prefer-readonly-parameter-types.test.ts b/packages/eslint-plugin/tests/rules/prefer-readonly-parameter-types.test.ts index 219b8cbdb086..1dbc1876057f 100644 --- a/packages/eslint-plugin/tests/rules/prefer-readonly-parameter-types.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-readonly-parameter-types.test.ts @@ -1,10 +1,12 @@ import type { TSESLint } from '@typescript-eslint/utils'; +import * as a from 'a'; import rule from '../../src/rules/prefer-readonly-parameter-types'; import type { InferMessageIdsTypeFromRule, InferOptionsTypeFromRule, } from '../../src/util'; +import * as util from '../../src/util'; import { getFixturesRootDir, noFormat, RuleTester } from '../RuleTester'; type MessageIds = InferMessageIdsTypeFromRule; @@ -362,6 +364,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, + ...util.readonlynessOptionsDefaults, + }, + ], + }, ], invalid: [ // arrays diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index 42dcc2ce9079..cac7690ea3a3 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -113,6 +113,10 @@ function isTypeReadonlyObject( return Readonlyness.Mutable; } + if (indexInfo.type === type) { + return Readonlyness.Readonly; + } + return isTypeReadonlyRecurser( checker, indexInfo.type,