From 81f393ffbd12ee69f818eb1f601d7c5f51f135d6 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Thu, 18 Feb 2021 21:57:19 +0000 Subject: [PATCH] Cherry-pick PR #42861 into release-4.2 Component commits: 21eb38bd7f Fix for crash when using ca call expression on private identifier coming from an any typed variable. (GH #42860) --- src/compiler/checker.ts | 11 +++++- .../reference/privateNameAndAny.errors.txt | 34 +++++++++++++++- .../baselines/reference/privateNameAndAny.js | 23 +++++++++++ .../reference/privateNameAndAny.symbols | 29 ++++++++++++++ .../reference/privateNameAndAny.types | 39 +++++++++++++++++++ .../members/privateNames/privateNameAndAny.ts | 11 ++++++ 6 files changed, 145 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e8693edb294db..d3274fc1c881e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21972,7 +21972,16 @@ namespace ts { const type = getTypeOfDottedName((node).expression, diagnostic); if (type) { const name = (node).name; - const prop = getPropertyOfType(type, isPrivateIdentifier(name) ? getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText) : name.escapedText); + let prop: Symbol | undefined; + if (isPrivateIdentifier(name)) { + if (!type.symbol) { + return undefined; + } + prop = getPropertyOfType(type, getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText)); + } + else { + prop = getPropertyOfType(type, name.escapedText); + } return prop && getExplicitTypeOfSymbol(prop, diagnostic); } return undefined; diff --git a/tests/baselines/reference/privateNameAndAny.errors.txt b/tests/baselines/reference/privateNameAndAny.errors.txt index 95130d6af41f5..51c072c43a83e 100644 --- a/tests/baselines/reference/privateNameAndAny.errors.txt +++ b/tests/baselines/reference/privateNameAndAny.errors.txt @@ -1,7 +1,14 @@ tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(5,15): error TS2339: Property '#bar' does not exist on type 'any'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(9,9): error TS2571: Object is of type 'unknown'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(10,9): error TS2571: Object is of type 'unknown'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(10,15): error TS2339: Property '#bar' does not exist on type 'any'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(11,9): error TS2571: Object is of type 'unknown'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(14,15): error TS2339: Property '#foo' does not exist on type 'never'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(15,15): error TS2339: Property '#bar' does not exist on type 'never'. +tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(16,15): error TS2339: Property '#foo' does not exist on type 'never'. -==== tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts (1 errors) ==== +==== tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts (8 errors) ==== class A { #foo = true; method(thing: any) { @@ -9,6 +16,31 @@ tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts(5,15): thing.#bar; // Error ~~~~ !!! error TS2339: Property '#bar' does not exist on type 'any'. + thing.#foo(); + } + methodU(thing: unknown) { + thing.#foo; + ~~~~~ +!!! error TS2571: Object is of type 'unknown'. + thing.#bar; + ~~~~~ +!!! error TS2571: Object is of type 'unknown'. + ~~~~ +!!! error TS2339: Property '#bar' does not exist on type 'any'. + thing.#foo(); + ~~~~~ +!!! error TS2571: Object is of type 'unknown'. + } + methodN(thing: never) { + thing.#foo; + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'never'. + thing.#bar; + ~~~~ +!!! error TS2339: Property '#bar' does not exist on type 'never'. + thing.#foo(); + ~~~~ +!!! error TS2339: Property '#foo' does not exist on type 'never'. } }; \ No newline at end of file diff --git a/tests/baselines/reference/privateNameAndAny.js b/tests/baselines/reference/privateNameAndAny.js index 83399f4aa4c8c..37d30dc1f5325 100644 --- a/tests/baselines/reference/privateNameAndAny.js +++ b/tests/baselines/reference/privateNameAndAny.js @@ -4,6 +4,17 @@ class A { method(thing: any) { thing.#foo; // OK thing.#bar; // Error + thing.#foo(); + } + methodU(thing: unknown) { + thing.#foo; + thing.#bar; + thing.#foo(); + } + methodN(thing: never) { + thing.#foo; + thing.#bar; + thing.#foo(); } }; @@ -24,6 +35,18 @@ class A { method(thing) { __classPrivateFieldGet(thing, _foo); // OK thing.; // Error + __classPrivateFieldGet(thing, _foo).call(// Error + thing); + } + methodU(thing) { + __classPrivateFieldGet(thing, _foo); + thing.; + __classPrivateFieldGet(thing, _foo).call(thing); + } + methodN(thing) { + __classPrivateFieldGet(thing, _foo); + thing.; + __classPrivateFieldGet(thing, _foo).call(thing); } } _foo = new WeakMap(); diff --git a/tests/baselines/reference/privateNameAndAny.symbols b/tests/baselines/reference/privateNameAndAny.symbols index 070938340cbe1..5a8c528e2ed9b 100644 --- a/tests/baselines/reference/privateNameAndAny.symbols +++ b/tests/baselines/reference/privateNameAndAny.symbols @@ -14,6 +14,35 @@ class A { thing.#bar; // Error >thing : Symbol(thing, Decl(privateNameAndAny.ts, 2, 11)) + + thing.#foo(); +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 2, 11)) + } + methodU(thing: unknown) { +>methodU : Symbol(A.methodU, Decl(privateNameAndAny.ts, 6, 5)) +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 7, 12)) + + thing.#foo; +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 7, 12)) + + thing.#bar; +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 7, 12)) + + thing.#foo(); +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 7, 12)) + } + methodN(thing: never) { +>methodN : Symbol(A.methodN, Decl(privateNameAndAny.ts, 11, 5)) +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 12, 12)) + + thing.#foo; +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 12, 12)) + + thing.#bar; +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 12, 12)) + + thing.#foo(); +>thing : Symbol(thing, Decl(privateNameAndAny.ts, 12, 12)) } }; diff --git a/tests/baselines/reference/privateNameAndAny.types b/tests/baselines/reference/privateNameAndAny.types index 89eed87858d61..4216626f5a73d 100644 --- a/tests/baselines/reference/privateNameAndAny.types +++ b/tests/baselines/reference/privateNameAndAny.types @@ -17,6 +17,45 @@ class A { thing.#bar; // Error >thing.#bar : any >thing : any + + thing.#foo(); +>thing.#foo() : any +>thing.#foo : any +>thing : any + } + methodU(thing: unknown) { +>methodU : (thing: unknown) => void +>thing : unknown + + thing.#foo; +>thing.#foo : any +>thing : unknown + + thing.#bar; +>thing.#bar : any +>thing : unknown + + thing.#foo(); +>thing.#foo() : any +>thing.#foo : any +>thing : unknown + } + methodN(thing: never) { +>methodN : (thing: never) => void +>thing : never + + thing.#foo; +>thing.#foo : any +>thing : never + + thing.#bar; +>thing.#bar : any +>thing : never + + thing.#foo(); +>thing.#foo() : any +>thing.#foo : any +>thing : never } }; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts b/tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts index 099e734594684..78fe2c9398452 100644 --- a/tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts +++ b/tests/cases/conformance/classes/members/privateNames/privateNameAndAny.ts @@ -6,5 +6,16 @@ class A { method(thing: any) { thing.#foo; // OK thing.#bar; // Error + thing.#foo(); + } + methodU(thing: unknown) { + thing.#foo; + thing.#bar; + thing.#foo(); + } + methodN(thing: never) { + thing.#foo; + thing.#bar; + thing.#foo(); } };