Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c7bac6f

Browse filesBrowse files
committed
Avoid getting undefined callSignatures/constructSignatures in getPropertyOfType
e350c35 (microsoft#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 microsoft#42350
1 parent a3ead92 commit c7bac6f
Copy full SHA for c7bac6f

9 files changed

+108-7Lines changed: 108 additions & 7 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+10-7Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3846,13 +3846,16 @@ namespace ts {
38463846
}
38473847

38483848
function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType {
3849-
(<ResolvedType>type).members = members;
3850-
(<ResolvedType>type).properties = members === emptySymbols ? emptyArray : getNamedMembers(members);
3851-
(<ResolvedType>type).callSignatures = callSignatures;
3852-
(<ResolvedType>type).constructSignatures = constructSignatures;
3853-
(<ResolvedType>type).stringIndexInfo = stringIndexInfo;
3854-
(<ResolvedType>type).numberIndexInfo = numberIndexInfo;
3855-
return <ResolvedType>type;
3849+
const resolved = <ResolvedType>type;
3850+
resolved.members = members;
3851+
resolved.properties = emptyArray;
3852+
resolved.callSignatures = callSignatures;
3853+
resolved.constructSignatures = constructSignatures;
3854+
resolved.stringIndexInfo = stringIndexInfo;
3855+
resolved.numberIndexInfo = numberIndexInfo;
3856+
// This can loop back to getPropertyOfType() which would crash if `callSignatures` & `constructSignatures` are not initialized.
3857+
if (members !== emptySymbols) resolved.properties = getNamedMembers(members);
3858+
return resolved;
38563859
}
38573860

38583861
function createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType {
Collapse file
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
tests/cases/conformance/salsa/x.js(1,9): error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.
2+
3+
4+
==== tests/cases/conformance/salsa/x.js (1 errors) ====
5+
exports.fn1();
6+
~~~
7+
!!! error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.
8+
exports.fn2 = Math.min;
9+
Collapse file
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/conformance/salsa/x.js ===
2+
exports.fn1();
3+
>exports : Symbol("tests/cases/conformance/salsa/x", Decl(x.js, 0, 0))
4+
5+
exports.fn2 = Math.min;
6+
>exports.fn2 : Symbol(fn2, Decl(x.js, 0, 14))
7+
>exports : Symbol(fn2, Decl(x.js, 0, 14))
8+
>fn2 : Symbol(fn2, Decl(x.js, 0, 14))
9+
>Math.min : Symbol(fn2, Decl(lib.es5.d.ts, --, --))
10+
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
11+
>min : Symbol(fn2, Decl(lib.es5.d.ts, --, --))
12+
Collapse file
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
=== tests/cases/conformance/salsa/x.js ===
2+
exports.fn1();
3+
>exports.fn1() : any
4+
>exports.fn1 : any
5+
>exports : typeof import("tests/cases/conformance/salsa/x")
6+
>fn1 : any
7+
8+
exports.fn2 = Math.min;
9+
>exports.fn2 = Math.min : (...values: number[]) => number
10+
>exports.fn2 : (...values: number[]) => number
11+
>exports : typeof import("tests/cases/conformance/salsa/x")
12+
>fn2 : (...values: number[]) => number
13+
>Math.min : (...values: number[]) => number
14+
>Math : Math
15+
>min : (...values: number[]) => number
16+
Collapse file
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
tests/cases/conformance/salsa/x.js(2,9): error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.
2+
3+
4+
==== tests/cases/conformance/salsa/x.js (1 errors) ====
5+
const Foo = { min: 3 };
6+
exports.fn1();
7+
~~~
8+
!!! error TS2339: Property 'fn1' does not exist on type 'typeof import("tests/cases/conformance/salsa/x")'.
9+
exports.fn2 = Foo.min;
10+
Collapse file
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
=== tests/cases/conformance/salsa/x.js ===
2+
const Foo = { min: 3 };
3+
>Foo : Symbol(Foo, Decl(x.js, 0, 5))
4+
>min : Symbol(min, Decl(x.js, 0, 13))
5+
6+
exports.fn1();
7+
>exports : Symbol("tests/cases/conformance/salsa/x", Decl(x.js, 0, 0))
8+
9+
exports.fn2 = Foo.min;
10+
>exports.fn2 : Symbol(fn2, Decl(x.js, 1, 14))
11+
>exports : Symbol(fn2, Decl(x.js, 1, 14))
12+
>fn2 : Symbol(fn2, Decl(x.js, 1, 14))
13+
>Foo.min : Symbol(fn2, Decl(x.js, 0, 13))
14+
>Foo : Symbol(Foo, Decl(x.js, 0, 5))
15+
>min : Symbol(fn2, Decl(x.js, 0, 13))
16+
Collapse file
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
=== tests/cases/conformance/salsa/x.js ===
2+
const Foo = { min: 3 };
3+
>Foo : { min: number; }
4+
>{ min: 3 } : { min: number; }
5+
>min : number
6+
>3 : 3
7+
8+
exports.fn1();
9+
>exports.fn1() : any
10+
>exports.fn1 : any
11+
>exports : typeof import("tests/cases/conformance/salsa/x")
12+
>fn1 : any
13+
14+
exports.fn2 = Foo.min;
15+
>exports.fn2 = Foo.min : number
16+
>exports.fn2 : number
17+
>exports : typeof import("tests/cases/conformance/salsa/x")
18+
>fn2 : number
19+
>Foo.min : number
20+
>Foo : { min: number; }
21+
>min : number
22+
Collapse file
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// @noEmit: true
2+
// @allowJs: true
3+
// @checkJs: true
4+
// @filename: x.js
5+
exports.fn1();
6+
exports.fn2 = Math.min;
Collapse file
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @noEmit: true
2+
// @allowJs: true
3+
// @checkJs: true
4+
// @filename: x.js
5+
const Foo = { min: 3 };
6+
exports.fn1();
7+
exports.fn2 = Foo.min;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.