Skip to content

Commit c774762

Browse files
authored
Fix crash in transformations (#33768)
1 parent 58854a6 commit c774762

File tree

14 files changed

+105
-13
lines changed

14 files changed

+105
-13
lines changed

src/compiler/factory.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,9 @@ namespace ts {
10651065
}
10661066

10671067
export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier) {
1068-
Debug.assert(!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessChain using updatePropertyAccess. Use updatePropertyAccessChain instead.");
1068+
if (isOptionalChain(node)) {
1069+
return updatePropertyAccessChain(node, expression, node.questionDotToken, name);
1070+
}
10691071
// Because we are updating existed propertyAccess we want to inherit its emitFlags
10701072
// instead of using the default from createPropertyAccess
10711073
return node.expression !== expression
@@ -1103,7 +1105,9 @@ namespace ts {
11031105
}
11041106

11051107
export function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) {
1106-
Debug.assert(!(node.flags & NodeFlags.OptionalChain), "Cannot update an ElementAccessChain using updateElementAccess. Use updateElementAccessChain instead.");
1108+
if (isOptionalChain(node)) {
1109+
return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression);
1110+
}
11071111
return node.expression !== expression
11081112
|| node.argumentExpression !== argumentExpression
11091113
? updateNode(createElementAccess(expression, argumentExpression), node)
@@ -1137,7 +1141,9 @@ namespace ts {
11371141
}
11381142

11391143
export function updateCall(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) {
1140-
Debug.assert(!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallChain using updateCall. Use updateCallChain instead.");
1144+
if (isOptionalChain(node)) {
1145+
return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray);
1146+
}
11411147
return node.expression !== expression
11421148
|| node.typeArguments !== typeArguments
11431149
|| node.arguments !== argumentsArray

src/compiler/utilities.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5906,9 +5906,11 @@ namespace ts {
59065906
}
59075907

59085908
export function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain {
5909-
return isPropertyAccessChain(node)
5910-
|| isElementAccessChain(node)
5911-
|| isCallChain(node);
5909+
const kind = node.kind;
5910+
return !!(node.flags & NodeFlags.OptionalChain) &&
5911+
(kind === SyntaxKind.PropertyAccessExpression
5912+
|| kind === SyntaxKind.ElementAccessExpression
5913+
|| kind === SyntaxKind.CallExpression);
59125914
}
59135915

59145916
export function isNewExpression(node: Node): node is NewExpression {

tests/baselines/reference/callChain.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ o3["b"]?.(1, ...[2, 3], 4).c;
3131

3232
declare const o4: undefined | (<T>(f: (a: T) => T) => T);
3333
declare function incr(x: number): number;
34-
const v: number | undefined = o4?.(incr);
34+
const v: number | undefined = o4?.(incr);
35+
36+
// GH#33744
37+
declare const o5: <T>() => undefined | (() => void);
38+
o5<number>()?.();
3539

3640
//// [callChain.js]
3741
"use strict";
@@ -42,7 +46,7 @@ var __spreadArrays = (this && this.__spreadArrays) || function () {
4246
r[k] = a[j];
4347
return r;
4448
};
45-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12;
49+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13;
4650
(_a = o1) === null || _a === void 0 ? void 0 : _a();
4751
(_b = o1) === null || _b === void 0 ? void 0 : _b(1);
4852
(_c = o1) === null || _c === void 0 ? void 0 : _c.apply(void 0, [1, 2]);
@@ -68,3 +72,4 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u,
6872
(_9 = (_8 = o3)["b"]) === null || _9 === void 0 ? void 0 : _9.call.apply(_9, __spreadArrays([_8], [1, 2])).c;
6973
(_11 = (_10 = o3)["b"]) === null || _11 === void 0 ? void 0 : _11.call.apply(_11, __spreadArrays([_10, 1], [2, 3], [4])).c;
7074
var v = (_12 = o4) === null || _12 === void 0 ? void 0 : _12(incr);
75+
(_13 = o5()) === null || _13 === void 0 ? void 0 : _13();

tests/baselines/reference/callChain.symbols

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,11 @@ const v: number | undefined = o4?.(incr);
148148
>o4 : Symbol(o4, Decl(callChain.ts, 30, 13))
149149
>incr : Symbol(incr, Decl(callChain.ts, 30, 57))
150150

151+
// GH#33744
152+
declare const o5: <T>() => undefined | (() => void);
153+
>o5 : Symbol(o5, Decl(callChain.ts, 35, 13))
154+
>T : Symbol(T, Decl(callChain.ts, 35, 19))
155+
156+
o5<number>()?.();
157+
>o5 : Symbol(o5, Decl(callChain.ts, 35, 13))
158+

tests/baselines/reference/callChain.types

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,12 @@ const v: number | undefined = o4?.(incr);
255255
>o4 : (<T>(f: (a: T) => T) => T) | undefined
256256
>incr : (x: number) => number
257257

258+
// GH#33744
259+
declare const o5: <T>() => undefined | (() => void);
260+
>o5 : <T>() => (() => void) | undefined
261+
262+
o5<number>()?.();
263+
>o5<number>()?.() : void | undefined
264+
>o5<number>() : (() => void) | undefined
265+
>o5 : <T>() => (() => void) | undefined
266+

tests/baselines/reference/elementAccessChain.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@ o5.b?.()["c"].d?.e;
1919
o5.b?.()["c"].d?.["e"];
2020
o5["b"]?.()["c"].d?.e;
2121
o5["b"]?.()["c"].d?.["e"];
22-
22+
23+
// GH#33744
24+
declare const o6: <T>() => undefined | ({ x: number });
25+
o6<number>()?.["x"];
2326

2427
//// [elementAccessChain.js]
2528
"use strict";
26-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
29+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
2730
(_a = o1) === null || _a === void 0 ? void 0 : _a["b"];
2831
(_b = o2) === null || _b === void 0 ? void 0 : _b["b"].c;
2932
(_c = o2) === null || _c === void 0 ? void 0 : _c.b["c"];
@@ -35,3 +38,4 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u,
3538
(_q = (_p = (_o = o5).b) === null || _p === void 0 ? void 0 : _p.call(_o)["c"].d) === null || _q === void 0 ? void 0 : _q["e"];
3639
(_t = (_s = (_r = o5)["b"]) === null || _s === void 0 ? void 0 : _s.call(_r)["c"].d) === null || _t === void 0 ? void 0 : _t.e;
3740
(_w = (_v = (_u = o5)["b"]) === null || _v === void 0 ? void 0 : _v.call(_u)["c"].d) === null || _w === void 0 ? void 0 : _w["e"];
41+
(_x = o6()) === null || _x === void 0 ? void 0 : _x["x"];

tests/baselines/reference/elementAccessChain.symbols

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,12 @@ o5["b"]?.()["c"].d?.["e"];
9797
>"b" : Symbol(b, Decl(elementAccessChain.ts, 15, 19))
9898
>d : Symbol(d, Decl(elementAccessChain.ts, 15, 32))
9999

100+
// GH#33744
101+
declare const o6: <T>() => undefined | ({ x: number });
102+
>o6 : Symbol(o6, Decl(elementAccessChain.ts, 22, 13))
103+
>T : Symbol(T, Decl(elementAccessChain.ts, 22, 19))
104+
>x : Symbol(x, Decl(elementAccessChain.ts, 22, 41))
105+
106+
o6<number>()?.["x"];
107+
>o6 : Symbol(o6, Decl(elementAccessChain.ts, 22, 13))
108+

tests/baselines/reference/elementAccessChain.types

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,14 @@ o5["b"]?.()["c"].d?.["e"];
130130
>d : { e: string; } | undefined
131131
>"e" : "e"
132132

133+
// GH#33744
134+
declare const o6: <T>() => undefined | ({ x: number });
135+
>o6 : <T>() => { x: number; } | undefined
136+
>x : number
137+
138+
o6<number>()?.["x"];
139+
>o6<number>()?.["x"] : number | undefined
140+
>o6<number>() : { x: number; } | undefined
141+
>o6 : <T>() => { x: number; } | undefined
142+
>"x" : "x"
143+

tests/baselines/reference/propertyAccessChain.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ o4.b?.c.d?.e;
1313

1414
declare const o5: { b?(): { c: { d?: { e: string } } } };
1515
o5.b?.().c.d?.e;
16-
16+
17+
// GH#33744
18+
declare const o6: <T>() => undefined | ({ x: number });
19+
o6<number>()?.x;
1720

1821
//// [propertyAccessChain.js]
1922
"use strict";
20-
var _a, _b, _c, _d, _e, _f, _g, _h;
23+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
2124
(_a = o1) === null || _a === void 0 ? void 0 : _a.b;
2225
(_b = o2) === null || _b === void 0 ? void 0 : _b.b.c;
2326
(_c = o3.b) === null || _c === void 0 ? void 0 : _c.c;
2427
(_e = (_d = o4.b) === null || _d === void 0 ? void 0 : _d.c.d) === null || _e === void 0 ? void 0 : _e.e;
2528
(_h = (_g = (_f = o5).b) === null || _g === void 0 ? void 0 : _g.call(_f).c.d) === null || _h === void 0 ? void 0 : _h.e;
29+
(_j = o6()) === null || _j === void 0 ? void 0 : _j.x;

tests/baselines/reference/propertyAccessChain.symbols

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,14 @@ o5.b?.().c.d?.e;
6868
>d : Symbol(d, Decl(propertyAccessChain.ts, 12, 32))
6969
>e : Symbol(e, Decl(propertyAccessChain.ts, 12, 38))
7070

71+
// GH#33744
72+
declare const o6: <T>() => undefined | ({ x: number });
73+
>o6 : Symbol(o6, Decl(propertyAccessChain.ts, 16, 13))
74+
>T : Symbol(T, Decl(propertyAccessChain.ts, 16, 19))
75+
>x : Symbol(x, Decl(propertyAccessChain.ts, 16, 41))
76+
77+
o6<number>()?.x;
78+
>o6<number>()?.x : Symbol(x, Decl(propertyAccessChain.ts, 16, 41))
79+
>o6 : Symbol(o6, Decl(propertyAccessChain.ts, 16, 13))
80+
>x : Symbol(x, Decl(propertyAccessChain.ts, 16, 41))
81+

tests/baselines/reference/propertyAccessChain.types

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,14 @@ o5.b?.().c.d?.e;
6969
>d : { e: string; } | undefined
7070
>e : string | undefined
7171

72+
// GH#33744
73+
declare const o6: <T>() => undefined | ({ x: number });
74+
>o6 : <T>() => { x: number; } | undefined
75+
>x : number
76+
77+
o6<number>()?.x;
78+
>o6<number>()?.x : number | undefined
79+
>o6<number>() : { x: number; } | undefined
80+
>o6 : <T>() => { x: number; } | undefined
81+
>x : number | undefined
82+

tests/cases/conformance/expressions/optionalChaining/callChain/callChain.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@ o3["b"]?.(1, ...[2, 3], 4).c;
3232

3333
declare const o4: undefined | (<T>(f: (a: T) => T) => T);
3434
declare function incr(x: number): number;
35-
const v: number | undefined = o4?.(incr);
35+
const v: number | undefined = o4?.(incr);
36+
37+
// GH#33744
38+
declare const o5: <T>() => undefined | (() => void);
39+
o5<number>()?.();

tests/cases/conformance/expressions/optionalChaining/elementAccessChain/elementAccessChain.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ o5.b?.()["c"].d?.e;
2020
o5.b?.()["c"].d?.["e"];
2121
o5["b"]?.()["c"].d?.e;
2222
o5["b"]?.()["c"].d?.["e"];
23+
24+
// GH#33744
25+
declare const o6: <T>() => undefined | ({ x: number });
26+
o6<number>()?.["x"];

tests/cases/conformance/expressions/optionalChaining/propertyAccessChain/propertyAccessChain.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ o4.b?.c.d?.e;
1414

1515
declare const o5: { b?(): { c: { d?: { e: string } } } };
1616
o5.b?.().c.d?.e;
17+
18+
// GH#33744
19+
declare const o6: <T>() => undefined | ({ x: number });
20+
o6<number>()?.x;

0 commit comments

Comments
 (0)