Skip to content

Commit

Permalink
Cherry-pick PR #42766 into release-4.2 (#42950)
Browse files Browse the repository at this point in the history
Component commits:
ed26816 Avoid getting undefined `callSignatures`/`constructSignatures` in `getPropertyOfType`
e350c35 (#40228) introduced a subtle bug: it switched the flags to an
alias, dropping `SymbolFlags.Property` --- and that makes
`symbolIsValue()` get to the `resolveAlias(symbol)` call, which leads to
`getPropertyOfType()` with`resolved.callSignatures`+`constructSignatures`
being `undefined`.  So initialize them in `setStructuredTypeMembers`
before calling `getNamedMembers()`.

Fixes #42350

Co-authored-by: Eli Barzilay <eli@barzilay.org>
  • Loading branch information
typescript-bot and elibarzilay committed Feb 25, 2021
1 parent e213b2a commit 822cb3a
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 7 deletions.
17 changes: 10 additions & 7 deletions src/compiler/checker.ts
Expand Up @@ -3846,13 +3846,16 @@ namespace ts {
}

function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType {
(<ResolvedType>type).members = members;
(<ResolvedType>type).properties = members === emptySymbols ? emptyArray : getNamedMembers(members);
(<ResolvedType>type).callSignatures = callSignatures;
(<ResolvedType>type).constructSignatures = constructSignatures;
(<ResolvedType>type).stringIndexInfo = stringIndexInfo;
(<ResolvedType>type).numberIndexInfo = numberIndexInfo;
return <ResolvedType>type;
const resolved = <ResolvedType>type;
resolved.members = members;
resolved.properties = emptyArray;
resolved.callSignatures = callSignatures;
resolved.constructSignatures = constructSignatures;
resolved.stringIndexInfo = stringIndexInfo;
resolved.numberIndexInfo = numberIndexInfo;
// This can loop back to getPropertyOfType() which would crash if `callSignatures` & `constructSignatures` are not initialized.
if (members !== emptySymbols) resolved.properties = getNamedMembers(members);
return resolved;
}

function createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType {
Expand Down
9 changes: 9 additions & 0 deletions tests/baselines/reference/moduleExportsAliasLoop1.errors.txt
@@ -0,0 +1,9 @@
tests/cases/conformance/salsa/x.js(1,9): error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.


==== tests/cases/conformance/salsa/x.js (1 errors) ====
exports.fn1();
~~~
!!! error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.
exports.fn2 = Math.min;

12 changes: 12 additions & 0 deletions tests/baselines/reference/moduleExportsAliasLoop1.symbols
@@ -0,0 +1,12 @@
=== tests/cases/conformance/salsa/x.js ===
exports.fn1();
>exports : Symbol("tests/cases/conformance/salsa/x", Decl(x.js, 0, 0))

exports.fn2 = Math.min;
>exports.fn2 : Symbol(fn2, Decl(x.js, 0, 14))
>exports : Symbol(fn2, Decl(x.js, 0, 14))
>fn2 : Symbol(fn2, Decl(x.js, 0, 14))
>Math.min : Symbol(fn2, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>min : Symbol(fn2, Decl(lib.es5.d.ts, --, --))

16 changes: 16 additions & 0 deletions tests/baselines/reference/moduleExportsAliasLoop1.types
@@ -0,0 +1,16 @@
=== tests/cases/conformance/salsa/x.js ===
exports.fn1();
>exports.fn1() : any
>exports.fn1 : any
>exports : typeof import("tests/cases/conformance/salsa/x")
>fn1 : any

exports.fn2 = Math.min;
>exports.fn2 = Math.min : (...values: number[]) => number
>exports.fn2 : (...values: number[]) => number
>exports : typeof import("tests/cases/conformance/salsa/x")
>fn2 : (...values: number[]) => number
>Math.min : (...values: number[]) => number
>Math : Math
>min : (...values: number[]) => number

10 changes: 10 additions & 0 deletions tests/baselines/reference/moduleExportsAliasLoop2.errors.txt
@@ -0,0 +1,10 @@
tests/cases/conformance/salsa/x.js(2,9): error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.


==== tests/cases/conformance/salsa/x.js (1 errors) ====
const Foo = { min: 3 };
exports.fn1();
~~~
!!! error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.
exports.fn2 = Foo.min;

16 changes: 16 additions & 0 deletions tests/baselines/reference/moduleExportsAliasLoop2.symbols
@@ -0,0 +1,16 @@
=== tests/cases/conformance/salsa/x.js ===
const Foo = { min: 3 };
>Foo : Symbol(Foo, Decl(x.js, 0, 5))
>min : Symbol(min, Decl(x.js, 0, 13))

exports.fn1();
>exports : Symbol("tests/cases/conformance/salsa/x", Decl(x.js, 0, 0))

exports.fn2 = Foo.min;
>exports.fn2 : Symbol(fn2, Decl(x.js, 1, 14))
>exports : Symbol(fn2, Decl(x.js, 1, 14))
>fn2 : Symbol(fn2, Decl(x.js, 1, 14))
>Foo.min : Symbol(fn2, Decl(x.js, 0, 13))
>Foo : Symbol(Foo, Decl(x.js, 0, 5))
>min : Symbol(fn2, Decl(x.js, 0, 13))

22 changes: 22 additions & 0 deletions tests/baselines/reference/moduleExportsAliasLoop2.types
@@ -0,0 +1,22 @@
=== tests/cases/conformance/salsa/x.js ===
const Foo = { min: 3 };
>Foo : { min: number; }
>{ min: 3 } : { min: number; }
>min : number
>3 : 3

exports.fn1();
>exports.fn1() : any
>exports.fn1 : any
>exports : typeof import("tests/cases/conformance/salsa/x")
>fn1 : any

exports.fn2 = Foo.min;
>exports.fn2 = Foo.min : number
>exports.fn2 : number
>exports : typeof import("tests/cases/conformance/salsa/x")
>fn2 : number
>Foo.min : number
>Foo : { min: number; }
>min : number

6 changes: 6 additions & 0 deletions tests/cases/conformance/salsa/moduleExportsAliasLoop1.ts
@@ -0,0 +1,6 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @filename: x.js
exports.fn1();
exports.fn2 = Math.min;
7 changes: 7 additions & 0 deletions tests/cases/conformance/salsa/moduleExportsAliasLoop2.ts
@@ -0,0 +1,7 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @filename: x.js
const Foo = { min: 3 };
exports.fn1();
exports.fn2 = Foo.min;

0 comments on commit 822cb3a

Please sign in to comment.