Skip to content

Commit a136f55

Browse files
authored
Fix stack overflow when resolving default construct signatures (#17878)
* Fix stack overflow when resolving default construct signatures * No need for || emptyArray
1 parent 45c62ac commit a136f55

File tree

5 files changed

+126
-6
lines changed

5 files changed

+126
-6
lines changed

src/compiler/checker.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -5657,17 +5657,12 @@ namespace ts {
56575657
else {
56585658
// Combinations of function, class, enum and module
56595659
let members = emptySymbols;
5660-
let constructSignatures: Signature[] = emptyArray;
56615660
let stringIndexInfo: IndexInfo = undefined;
56625661
if (symbol.exports) {
56635662
members = getExportsOfSymbol(symbol);
56645663
}
56655664
if (symbol.flags & SymbolFlags.Class) {
56665665
const classType = getDeclaredTypeOfClassOrInterface(symbol);
5667-
constructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor));
5668-
if (!constructSignatures.length) {
5669-
constructSignatures = getDefaultConstructSignatures(classType);
5670-
}
56715666
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
56725667
if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.TypeVariable)) {
56735668
members = createSymbolTable(getNamedMembers(members));
@@ -5678,14 +5673,23 @@ namespace ts {
56785673
}
56795674
}
56805675
const numberIndexInfo = symbol.flags & SymbolFlags.Enum ? enumNumberIndexInfo : undefined;
5681-
setStructuredTypeMembers(type, members, emptyArray, constructSignatures, stringIndexInfo, numberIndexInfo);
5676+
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
56825677
// We resolve the members before computing the signatures because a signature may use
56835678
// typeof with a qualified name expression that circularly references the type we are
56845679
// in the process of resolving (see issue #6072). The temporarily empty signature list
56855680
// will never be observed because a qualified name can't reference signatures.
56865681
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
56875682
(<ResolvedType>type).callSignatures = getSignaturesOfSymbol(symbol);
56885683
}
5684+
// And likewise for construct signatures for classes
5685+
if (symbol.flags & SymbolFlags.Class) {
5686+
const classType = getDeclaredTypeOfClassOrInterface(symbol);
5687+
let constructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor));
5688+
if (!constructSignatures.length) {
5689+
constructSignatures = getDefaultConstructSignatures(classType);
5690+
}
5691+
(<ResolvedType>type).constructSignatures = constructSignatures;
5692+
}
56895693
}
56905694
}
56915695

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [cloduleGenericOnSelfMember.ts]
2+
class ServiceBase<T> {
3+
field: T;
4+
}
5+
class Service extends ServiceBase<typeof Service.Base> {
6+
}
7+
namespace Service {
8+
export const Base = {
9+
name: "1",
10+
value: 5
11+
};
12+
}
13+
14+
//// [cloduleGenericOnSelfMember.js]
15+
var __extends = (this && this.__extends) || (function () {
16+
var extendStatics = Object.setPrototypeOf ||
17+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
18+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
19+
return function (d, b) {
20+
extendStatics(d, b);
21+
function __() { this.constructor = d; }
22+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
23+
};
24+
})();
25+
var ServiceBase = /** @class */ (function () {
26+
function ServiceBase() {
27+
}
28+
return ServiceBase;
29+
}());
30+
var Service = /** @class */ (function (_super) {
31+
__extends(Service, _super);
32+
function Service() {
33+
return _super !== null && _super.apply(this, arguments) || this;
34+
}
35+
return Service;
36+
}(ServiceBase));
37+
(function (Service) {
38+
Service.Base = {
39+
name: "1",
40+
value: 5
41+
};
42+
})(Service || (Service = {}));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/compiler/cloduleGenericOnSelfMember.ts ===
2+
class ServiceBase<T> {
3+
>ServiceBase : Symbol(ServiceBase, Decl(cloduleGenericOnSelfMember.ts, 0, 0))
4+
>T : Symbol(T, Decl(cloduleGenericOnSelfMember.ts, 0, 18))
5+
6+
field: T;
7+
>field : Symbol(ServiceBase.field, Decl(cloduleGenericOnSelfMember.ts, 0, 22))
8+
>T : Symbol(T, Decl(cloduleGenericOnSelfMember.ts, 0, 18))
9+
}
10+
class Service extends ServiceBase<typeof Service.Base> {
11+
>Service : Symbol(Service, Decl(cloduleGenericOnSelfMember.ts, 2, 1), Decl(cloduleGenericOnSelfMember.ts, 4, 1))
12+
>ServiceBase : Symbol(ServiceBase, Decl(cloduleGenericOnSelfMember.ts, 0, 0))
13+
>Service.Base : Symbol(Service.Base, Decl(cloduleGenericOnSelfMember.ts, 6, 16))
14+
>Service : Symbol(Service, Decl(cloduleGenericOnSelfMember.ts, 2, 1), Decl(cloduleGenericOnSelfMember.ts, 4, 1))
15+
>Base : Symbol(Service.Base, Decl(cloduleGenericOnSelfMember.ts, 6, 16))
16+
}
17+
namespace Service {
18+
>Service : Symbol(Service, Decl(cloduleGenericOnSelfMember.ts, 2, 1), Decl(cloduleGenericOnSelfMember.ts, 4, 1))
19+
20+
export const Base = {
21+
>Base : Symbol(Base, Decl(cloduleGenericOnSelfMember.ts, 6, 16))
22+
23+
name: "1",
24+
>name : Symbol(name, Decl(cloduleGenericOnSelfMember.ts, 6, 25))
25+
26+
value: 5
27+
>value : Symbol(value, Decl(cloduleGenericOnSelfMember.ts, 7, 18))
28+
29+
};
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/cloduleGenericOnSelfMember.ts ===
2+
class ServiceBase<T> {
3+
>ServiceBase : ServiceBase<T>
4+
>T : T
5+
6+
field: T;
7+
>field : T
8+
>T : T
9+
}
10+
class Service extends ServiceBase<typeof Service.Base> {
11+
>Service : Service
12+
>ServiceBase : ServiceBase<{ name: string; value: number; }>
13+
>Service.Base : { name: string; value: number; }
14+
>Service : typeof Service
15+
>Base : { name: string; value: number; }
16+
}
17+
namespace Service {
18+
>Service : typeof Service
19+
20+
export const Base = {
21+
>Base : { name: string; value: number; }
22+
>{ name: "1", value: 5 } : { name: string; value: number; }
23+
24+
name: "1",
25+
>name : string
26+
>"1" : "1"
27+
28+
value: 5
29+
>value : number
30+
>5 : 5
31+
32+
};
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class ServiceBase<T> {
2+
field: T;
3+
}
4+
class Service extends ServiceBase<typeof Service.Base> {
5+
}
6+
namespace Service {
7+
export const Base = {
8+
name: "1",
9+
value: 5
10+
};
11+
}

0 commit comments

Comments
 (0)