From d3cbe8279d65a6e7bb17d1bf82b3e2dcd13aec2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 5 Mar 2025 00:17:54 +0100 Subject: [PATCH] Fixed crash in `hasVisibleDeclarations` related to binding elements --- src/compiler/checker.ts | 9 ++- ...ndingElementDeclarationNoCrash1.errors.txt | 28 +++++++ ...yBindingElementDeclarationNoCrash1.symbols | 51 ++++++++++++ ...rtyBindingElementDeclarationNoCrash1.types | 78 +++++++++++++++++++ ...opertyBindingElementDeclarationNoCrash1.ts | 22 ++++++ 5 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.errors.txt create mode 100644 tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.symbols create mode 100644 tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.types create mode 100644 tests/cases/compiler/computedPropertyBindingElementDeclarationNoCrash1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index caab75c99fa8a..0e272303c4932 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5908,7 +5908,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return addVisibleAlias(declaration, declaration.parent.parent.parent.parent); } else if (symbol.flags & SymbolFlags.BlockScopedVariable) { - const variableStatement = findAncestor(declaration, isVariableStatement)!; + const rootDeclaration = walkUpBindingElementsAndPatterns(declaration); + if (rootDeclaration.kind === SyntaxKind.Parameter) { + return false; + } + const variableStatement = rootDeclaration.parent.parent; + if (variableStatement.kind !== SyntaxKind.VariableStatement) { + return false; + } if (hasSyntacticModifier(variableStatement, ModifierFlags.Export)) { return true; } diff --git a/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.errors.txt b/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.errors.txt new file mode 100644 index 0000000000000..f312f6c37d01f --- /dev/null +++ b/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.errors.txt @@ -0,0 +1,28 @@ +computedPropertyBindingElementDeclarationNoCrash1.ts(12,21): error TS2345: Argument of type '{ [x: string]: unknown; }' is not assignable to parameter of type 'State'. + Type '{ [x: string]: unknown; }' is missing the following properties from type 'State': a, b + + +==== computedPropertyBindingElementDeclarationNoCrash1.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/61351 + + export type State = { + a: number; + b: string; + }; + + export class Test { + setState(state: State) {} + test = (e: any) => { + for (const [key, value] of Object.entries(e)) { + this.setState({ + ~ + [key]: value, + ~~~~~~~~~~~~~~~~~~~~~ + }); + ~~~~~~~ +!!! error TS2345: Argument of type '{ [x: string]: unknown; }' is not assignable to parameter of type 'State'. +!!! error TS2345: Type '{ [x: string]: unknown; }' is missing the following properties from type 'State': a, b + } + }; + } + \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.symbols b/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.symbols new file mode 100644 index 0000000000000..f7edf98d7ee40 --- /dev/null +++ b/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/computedPropertyBindingElementDeclarationNoCrash1.ts] //// + +=== computedPropertyBindingElementDeclarationNoCrash1.ts === +// https://github.com/microsoft/TypeScript/issues/61351 + +export type State = { +>State : Symbol(State, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 0, 0)) + + a: number; +>a : Symbol(a, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 2, 21)) + + b: string; +>b : Symbol(b, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 3, 12)) + +}; + +export class Test { +>Test : Symbol(Test, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 5, 2)) + + setState(state: State) {} +>setState : Symbol(Test.setState, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 7, 19)) +>state : Symbol(state, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 8, 11)) +>State : Symbol(State, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 0, 0)) + + test = (e: any) => { +>test : Symbol(Test.test, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 8, 27)) +>e : Symbol(e, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 9, 10)) + + for (const [key, value] of Object.entries(e)) { +>key : Symbol(key, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 10, 16)) +>value : Symbol(value, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 10, 20)) +>Object.entries : Symbol(ObjectConstructor.entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>entries : Symbol(ObjectConstructor.entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --)) +>e : Symbol(e, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 9, 10)) + + this.setState({ +>this.setState : Symbol(Test.setState, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 7, 19)) +>this : Symbol(Test, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 5, 2)) +>setState : Symbol(Test.setState, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 7, 19)) + + [key]: value, +>[key] : Symbol([key], Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 11, 21)) +>key : Symbol(key, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 10, 16)) +>value : Symbol(value, Decl(computedPropertyBindingElementDeclarationNoCrash1.ts, 10, 20)) + + }); + } + }; +} + diff --git a/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.types b/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.types new file mode 100644 index 0000000000000..f8555f7fd3e3a --- /dev/null +++ b/tests/baselines/reference/computedPropertyBindingElementDeclarationNoCrash1.types @@ -0,0 +1,78 @@ +//// [tests/cases/compiler/computedPropertyBindingElementDeclarationNoCrash1.ts] //// + +=== computedPropertyBindingElementDeclarationNoCrash1.ts === +// https://github.com/microsoft/TypeScript/issues/61351 + +export type State = { +>State : State +> : ^^^^^ + + a: number; +>a : number +> : ^^^^^^ + + b: string; +>b : string +> : ^^^^^^ + +}; + +export class Test { +>Test : Test +> : ^^^^ + + setState(state: State) {} +>setState : (state: State) => void +> : ^ ^^ ^^^^^^^^^ +>state : State +> : ^^^^^ + + test = (e: any) => { +>test : (e: any) => void +> : ^ ^^ ^^^^^^^^^ +>(e: any) => { for (const [key, value] of Object.entries(e)) { this.setState({ [key]: value, }); } } : (e: any) => void +> : ^ ^^ ^^^^^^^^^ +>e : any +> : ^^^ + + for (const [key, value] of Object.entries(e)) { +>key : string +> : ^^^^^^ +>value : unknown +> : ^^^^^^^ +>Object.entries(e) : [string, unknown][] +> : ^^^^^^^^^^^^^^^^^^^ +>Object.entries : { (o: { [s: string]: T; } | ArrayLike): [string, T][]; (o: {}): [string, any][]; } +> : ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^ +>Object : ObjectConstructor +> : ^^^^^^^^^^^^^^^^^ +>entries : { (o: { [s: string]: T; } | ArrayLike): [string, T][]; (o: {}): [string, any][]; } +> : ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^ +>e : any +> : ^^^ + + this.setState({ +>this.setState({ [key]: value, }) : void +> : ^^^^ +>this.setState : (state: State) => void +> : ^ ^^ ^^^^^^^^^ +>this : this +> : ^^^^ +>setState : (state: State) => void +> : ^ ^^ ^^^^^^^^^ +>{ [key]: value, } : { [x: string]: unknown; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + [key]: value, +>[key] : unknown +> : ^^^^^^^ +>key : string +> : ^^^^^^ +>value : unknown +> : ^^^^^^^ + + }); + } + }; +} + diff --git a/tests/cases/compiler/computedPropertyBindingElementDeclarationNoCrash1.ts b/tests/cases/compiler/computedPropertyBindingElementDeclarationNoCrash1.ts new file mode 100644 index 0000000000000..5b1fb8d5c928a --- /dev/null +++ b/tests/cases/compiler/computedPropertyBindingElementDeclarationNoCrash1.ts @@ -0,0 +1,22 @@ +// @strict: true +// @target: esnext +// @lib: esnext +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/61351 + +export type State = { + a: number; + b: string; +}; + +export class Test { + setState(state: State) {} + test = (e: any) => { + for (const [key, value] of Object.entries(e)) { + this.setState({ + [key]: value, + }); + } + }; +}