Skip to content

Commit 315f9f9

Browse files
TypeScript Botjakebailey
TypeScript Bot
andauthored
🤖 Pick PR #59285 (Fix captured shorthand properties i...) into release-5.5 (#59307)
Co-authored-by: Jake Bailey <[email protected]>
1 parent afe1c32 commit 315f9f9

6 files changed

+136
-2
lines changed

‎src/compiler/checker.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49238,11 +49238,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4923849238
forEachNodeRecursively(node, checkIdentifiers);
4923949239
}
4924049240

49241+
function isExpressionNodeOrShorthandPropertyAssignmentName(node: Identifier) {
49242+
// TODO(jakebailey): Just use isExpressionNode once that considers these identifiers to be expressions.
49243+
return isExpressionNode(node)
49244+
|| isShorthandPropertyAssignment(node.parent) && (node.parent.objectAssignmentInitializer ?? node.parent.name) === node;
49245+
}
49246+
4924149247
function checkSingleIdentifier(node: Node) {
4924249248
const nodeLinks = getNodeLinks(node);
4924349249
nodeLinks.calculatedFlags |= NodeCheckFlags.ConstructorReference | NodeCheckFlags.CapturedBlockScopedBinding | NodeCheckFlags.BlockScopedBindingInLoop;
49244-
if (isIdentifier(node) && isExpressionNode(node) && !(isPropertyAccessExpression(node.parent) && node.parent.name === node)) {
49245-
const s = getSymbolAtLocation(node, /*ignoreErrors*/ true);
49250+
if (isIdentifier(node) && isExpressionNodeOrShorthandPropertyAssignmentName(node) && !(isPropertyAccessExpression(node.parent) && node.parent.name === node)) {
49251+
const s = getResolvedSymbol(node);
4924649252
if (s && s !== unknownSymbol) {
4924749253
checkIdentifierCalculateNodeCheckFlags(node, s);
4924849254
}

‎src/compiler/utilities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3493,6 +3493,7 @@ export function isInExpressionContext(node: Node): boolean {
34933493
case SyntaxKind.ExpressionWithTypeArguments:
34943494
return (parent as ExpressionWithTypeArguments).expression === node && !isPartOfTypeNode(parent);
34953495
case SyntaxKind.ShorthandPropertyAssignment:
3496+
// TODO(jakebailey): it's possible that node could be the name, too
34963497
return (parent as ShorthandPropertyAssignment).objectAssignmentInitializer === node;
34973498
case SyntaxKind.SatisfiesExpression:
34983499
return node === (parent as SatisfiesExpression).expression;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [tests/cases/compiler/capturedShorthandPropertyAssignmentNoCheck.ts] ////
2+
3+
//// [capturedShorthandPropertyAssignmentNoCheck.ts]
4+
const fns = [];
5+
for (const value of [1, 2, 3]) {
6+
fns.push(() => ({ value }));
7+
}
8+
const result = fns.map(fn => fn());
9+
console.log(result)
10+
11+
12+
//// [capturedShorthandPropertyAssignmentNoCheck.js]
13+
var fns = [];
14+
var _loop_1 = function (value) {
15+
fns.push(function () { return ({ value: value }); });
16+
};
17+
for (var _i = 0, _a = [1, 2, 3]; _i < _a.length; _i++) {
18+
var value = _a[_i];
19+
_loop_1(value);
20+
}
21+
var result = fns.map(function (fn) { return fn(); });
22+
console.log(result);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [tests/cases/compiler/capturedShorthandPropertyAssignmentNoCheck.ts] ////
2+
3+
=== capturedShorthandPropertyAssignmentNoCheck.ts ===
4+
const fns = [];
5+
>fns : Symbol(fns, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 0, 5))
6+
7+
for (const value of [1, 2, 3]) {
8+
>value : Symbol(value, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 1, 10))
9+
10+
fns.push(() => ({ value }));
11+
>fns.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
12+
>fns : Symbol(fns, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 0, 5))
13+
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
14+
>value : Symbol(value, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 2, 21))
15+
}
16+
const result = fns.map(fn => fn());
17+
>result : Symbol(result, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 4, 5))
18+
>fns.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
19+
>fns : Symbol(fns, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 0, 5))
20+
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
21+
>fn : Symbol(fn, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 4, 23))
22+
>fn : Symbol(fn, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 4, 23))
23+
24+
console.log(result)
25+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
26+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
27+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
28+
>result : Symbol(result, Decl(capturedShorthandPropertyAssignmentNoCheck.ts, 4, 5))
29+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//// [tests/cases/compiler/capturedShorthandPropertyAssignmentNoCheck.ts] ////
2+
3+
=== capturedShorthandPropertyAssignmentNoCheck.ts ===
4+
const fns = [];
5+
>fns : any[]
6+
> : ^^^^^
7+
>[] : undefined[]
8+
> : ^^^^^^^^^^^
9+
10+
for (const value of [1, 2, 3]) {
11+
>value : number
12+
> : ^^^^^^
13+
>[1, 2, 3] : number[]
14+
> : ^^^^^^^^
15+
>1 : 1
16+
> : ^
17+
>2 : 2
18+
> : ^
19+
>3 : 3
20+
> : ^
21+
22+
fns.push(() => ({ value }));
23+
>fns.push(() => ({ value })) : number
24+
> : ^^^^^^
25+
>fns.push : (...items: any[]) => number
26+
> : ^^^^ ^^^^^^^^^^^^
27+
>fns : any[]
28+
> : ^^^^^
29+
>push : (...items: any[]) => number
30+
> : ^^^^ ^^^^^^^^^^^^
31+
>() => ({ value }) : () => { value: number; }
32+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
33+
>({ value }) : { value: number; }
34+
> : ^^^^^^^^^^^^^^^^^^
35+
>{ value } : { value: number; }
36+
> : ^^^^^^^^^^^^^^^^^^
37+
>value : number
38+
> : ^^^^^^
39+
}
40+
const result = fns.map(fn => fn());
41+
>result : any[]
42+
> : ^^^^^
43+
>fns.map(fn => fn()) : any[]
44+
> : ^^^^^
45+
>fns.map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
46+
> : ^ ^^ ^^^ ^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^^ ^^^^^^
47+
>fns : any[]
48+
> : ^^^^^
49+
>map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
50+
> : ^ ^^ ^^^ ^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^^ ^^^^^^
51+
>fn => fn() : (fn: any) => any
52+
> : ^ ^^^^^^^^^^^^^
53+
>fn : any
54+
>fn() : any
55+
>fn : any
56+
57+
console.log(result)
58+
>console.log(result) : void
59+
> : ^^^^
60+
>console.log : (...data: any[]) => void
61+
> : ^^^^ ^^ ^^^^^
62+
>console : Console
63+
> : ^^^^^^^
64+
>log : (...data: any[]) => void
65+
> : ^^^^ ^^ ^^^^^
66+
>result : any[]
67+
> : ^^^^^
68+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @target: es5
2+
3+
const fns = [];
4+
for (const value of [1, 2, 3]) {
5+
fns.push(() => ({ value }));
6+
}
7+
const result = fns.map(fn => fn());
8+
console.log(result)

0 commit comments

Comments
 (0)